Merged heads. Fixed conflicts in cvars.inc and zadmin.inc.

Readded some functions in zadmin.inc, but made them as comments. No reason to remove these so we don't have to remake them again.
This commit is contained in:
richard 2009-05-30 04:42:23 +02:00
commit 1fb33b2b13
44 changed files with 2843 additions and 2585 deletions

View File

@ -1,120 +0,0 @@
Changes from Zombie: Reloaded 2.5.1
====================================
Alpha values (transparency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for alpha values in classes. New values in classes.txt (per class):
Key: Value: Default: Description:
alpha_spawn <0-255> 255 initial alpha value (0 = transparent)
alpha_damaged <0-255> 255 alpha value when damaged
alpha_damage <damage> 0 how much damage to do before
alpha_damaged take effect
Knockback multiplier
~~~~~~~~~~~~~~~~~~~~~
If classes are enabled the zr_zombie_knockback cvar is used as a multiplier.
Makes it possible to set custom knockback on maps using per-map configs.
Set zr_zombie_knockback to 1 if you use classes and want it the way it was
before.
knockback = zr_zombie_knockback * class knockback
Full spawn protection
~~~~~~~~~~~~~~~~~~~~~~
Spawn protection makes the players invisible and move faster, and cannot be
infected during protection time.
A centered counter shows the time remaining.
Overriding class night vision
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for overrriding class nvgs with the zr_zombie_nvgs cvar. Generally,
any non-zero value is considered as on.
Value: Description:
-1 no override (use value in classes.txt) / nvgs on
0 never give nvgs
1 always give nvgs
Anticamp feature
~~~~~~~~~~~~~~~~~
Define hurt volumes in maps that gives x damage at a custom interval.
When creating volumes they should start a little bit _below_ the floor, so it
covers the players feet.
The volume is rectangular and you only need two locations in the map to create
it; a top corner, and the bottom corner at the oposite side.
zr_anticamp_create_volume <damage> <interval> <x1> <y1> <z1> <x2> <y2> <z2>
- Create a rectangular volume between the specified locations.
zr_anticamp_remove_volume <volume id>
- Remove a volume.
zr_anticamp_list
- List existing volumes.
Set default classes
~~~~~~~~~~~~~~~~~~~~
Setting the default class with a cvar. Works with per-map configs. Use "random"
as classname to set random classes on all players when the map loads or they
connect.
zr_classes_default <classname>
Zombie admin menu
~~~~~~~~~~~~~~~~~~
Basic zombie admin commands like adjusting knockback, nvgs, infecting players
and spawn everyone.
Knockback changes are applied instantly, useful for tuning knockback in-game.
Note that the changes are not saved. They will reset on map change. In a
future version this menu might save the changes.
Knockback multiplier
- Fine tune the knockback multiplier.
Class knockback
- Fine tune a class knockback value.
Night vision settings
- Override night vision settings (explained earlier).
Infect
- Infect a player. Lists all players, but could be changed to only list
humans.
Spawn players
- Spawns all dead players (except spectactors).
(more zombie admin stuff might come...)
Set (and get) class knockback
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set or get knockback from a class. Changes are not saved. They will be reset on
map change.
zr_set_class_knockback <classname> <knockback>
- Sets knockback to a specified class. Useful when using per-map configs to
fine tune the class knockback for a map.
zr_get_class_knockback <classname>
- Prints the current knockback of a class to the client/server console.
Using the zombie admin menu to read a knockback value is easier sometimes.
More stuff
~~~~~~~~~~~
Other minior and major bug fixes. See changelog.txt.

View File

@ -4,7 +4,7 @@
// //
// "hitgroup index" // Index of the hitgroup (listed below) // "hitgroup index" // Index of the hitgroup (listed below)
// { // {
// "name" "name of hitgroup" // Redundant as of now, used for readability. // "index" "name of hitgroup" // Redundant as of now, used for readability.
// "knockback" "1.0" (default) // The knockback multiplier for the hitgroup. // "knockback" "1.0" (default) // The knockback multiplier for the hitgroup.
// "damage" "yes" (default // Toggle damage on and off for this hitgroup. // "damage" "yes" (default // Toggle damage on and off for this hitgroup.
// } // }
@ -13,68 +13,130 @@
// //
// A missing config setting will be assumed to be its default value (documented above). // A missing config setting will be assumed to be its default value (documented above).
// ============================================================================
//
// ZOMBIE:RELOADED
// Hitgroup configurations
//
// Check the hitgroup configuration section in the manual for detailed info.
//
// ============================================================================
//
// SHORT DESCRIPTIONS
//
// Attribute: Values: Description:
// ----------------------------------------------------------------------------
// index number The hitgroup index
// damage yes/no Allow damage to be done on this hitgroup for zombies.
// knockback decimal The knockback multiplier for this hitgroup.
"hitgroups" // Counter-Strike: Source hitgroups "hitgroups" // Counter-Strike: Source hitgroups
{ {
"0" "Generic"
{ {
"name" "Generic" // General
"knockback" "1.0" "index" "0"
// Damage
"damage" "yes" "damage" "yes"
// Knockback
"knockback" "1.0"
} }
"1" "Head"
{ {
"name" "Head" // General
"index" "1"
// Damage
"damage" "yes"
// Knockback
"knockback" "2.0" "knockback" "2.0"
"damage" "yes"
} }
"2" "Chest"
{ {
"name" "Chest" // General
"index" "2"
// Damage
"damage" "yes"
// Knockback
"knockback" "1.3" "knockback" "1.3"
"damage" "yes"
} }
"3" "Stomach"
{ {
"name" "Stomach" // General
"index" "3"
// Damage
"damage" "yes"
// Knockback
"knockback" "1.2" "knockback" "1.2"
"damage" "yes"
} }
"4" "Left Arm"
{ {
"name" "Left Arm" // General
"index" "4"
// Damage
"damage" "yes"
// Knockback
"knockback" "1.0" "knockback" "1.0"
"damage" "yes"
} }
"5" "Right Arm"
{ {
"name" "Right Arm" // General
"index" "5"
// Damage
"damage" "yes"
// Knockback
"knockback" "1.0" "knockback" "1.0"
"damage" "yes"
} }
"6" "Left Leg"
{ {
"name" "Left Leg" // General
"index" "6"
// Damage
"damage" "yes"
// Knockback
"knockback" "0.9" "knockback" "0.9"
"damage" "yes"
} }
"7" "Right Leg"
{ {
"name" "Right Leg" // General
"index" "7"
// Damage
"damage" "yes"
// Knockback
"knockback" "0.9" "knockback" "0.9"
"damage" "yes"
} }
"10" "Gear"
{ {
"name" "Gear" // General
"knockback" "1.0" "index" "8"
// Damage
"damage" "yes" "damage" "yes"
// Knockback
"knockback" "1.0"
} }
} }

View File

@ -0,0 +1,713 @@
// ============================================================================
//
// ZOMBIE:RELOADED
// Weapon configurations
//
// Check the weapon configuration section in the manual for detailed info.
//
// ============================================================================
//
// SHORT DESCRIPTIONS
//
// Attribute: Values: Description:
// ----------------------------------------------------------------------------
// weapontype text The type of weapon it is. (List types, separate by ", "
// restrictdefault yes/no The default restricted status of the weapon on map start.
// toggleable yes/no Enable weapon to have restrictions toggled mid-game.
// ammotype text Ammo entity that belongs to weapons. (Don't change this)
// ammoprice number Price of ammo for this weapon.
// knockback decimal The knockback multiplier for the weapon. ['0.5' = half knockback | 2.0 = double]
// zmarketprice number The price of the weapon in ZMarket. (Defaulted to CS:S buymenu price)
"weapons" // Counter-Strike: Source weapons
{
"Glock"
{
// General
"weapontype" "All, Pistol"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_9mm"
"ammoprice" "100"
// Knockback (module)
"knockback" "0.8"
// ZMarket (module)
"zmarketprice" "400"
}
"USP"
{
// General
"weapontype" "All, Pistol"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_45acp"
"ammoprice" "100"
// Knockback (module)
"knockback" "0.8"
// ZMarket (module)
"zmarketprice" "500"
}
"P228"
{
// General
"weapontype" "All, Pistol"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_357sig"
"ammoprice" "100"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "600"
}
"Deagle"
{
// General
"weapontype" "All, Pistol"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_50ae"
"ammoprice" "100"
// Knockback (module)
"knockback" "1.2"
// ZMarket (module)
"zmarketprice" "650"
}
"Elite"
{
// General
"weapontype" "All, Pistol"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_9mm"
"ammoprice" "100"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "800"
}
"Fiveseven"
{
// General
"weapontype" "All, Pistol"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_57mm"
"ammoprice" "100"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "750"
}
"M3"
{
// General
"weapontype" "All, Shotgun"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_buckshot"
"ammoprice" "300"
// Knockback (module)
"knockback" "0.9" // Remember that there are 8 pellets in 1 shot.
// ZMarket (module)
"zmarketprice" "1700"
}
"XM1014"
{
// General
"weapontype" "All, Shotgun"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_buckshot"
"ammoprice" "300"
// Knockback (module)
"knockback" "0.8" // See above comment.
// ZMarket (module)
"zmarketprice" "3000"
}
"Mac10"
{
// General
"weapontype" "All, SMG"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_45acp"
"ammoprice" "300"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "1400"
}
"TMP"
{
// General
"weapontype" "All, SMG"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_9mm"
"ammoprice" "300"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "1250"
}
"MP5Navy"
{
// General
"weapontype" "All, SMG"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_9mm"
"ammoprice" "300"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "1500"
}
"UMP45"
{
// General
"weapontype" "All, SMG"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_45acp"
"ammoprice" "300"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "1700"
}
"P90"
{
// General
"weapontype" "All, SMG"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_57mm"
"ammoprice" "300"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "2350"
}
"Galil"
{
// General
"weapontype" "All, Rifle"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_556mm"
"ammoprice" "500"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "2000"
}
"Famas"
{
// General
"weapontype" "All, Rifle"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_556mm"
"ammoprice" "500"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "2250"
}
"AK47"
{
// General
"weapontype" "All, Rifle"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_762mm"
"ammoprice" "500"
// Knockback (module)
"knockback" "1.2"
// ZMarket (module)
"zmarketprice" "2500"
}
"M4A1"
{
// General
"weapontype" "All, Rifle"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_556mm"
"ammoprice" "500"
// Knockback (module)
"knockback" "1.1"
// ZMarket (module)
"zmarketprice" "3100"
}
"SG552"
{
// General
"weapontype" "All, Rifle"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_556mm"
"ammoprice" "500"
// Knockback (module)
"knockback" "1.0"
// ZMarket (module)
"zmarketprice" "3500"
}
"AUG"
{
// General
"weapontype" "All, Rifle"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_762mm"
"ammoprice" "500"
// Knockback (module)
"knockback" "1.1"
// ZMarket (module)
"zmarketprice" "3500"
}
"Scout"
{
// General
"weapontype" "All, Sniper"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_762mm"
"ammoprice" "750"
// Knockback (module)
"knockback" "1.5"
// ZMarket (module)
"zmarketprice" "2750"
}
"SG550"
{
// General
"weapontype" "All, Sniper"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_556mm"
"ammoprice" "1000"
// Knockback (module)
"knockback" "1.3"
// ZMarket (module)
"zmarketprice" "4200"
}
"G3SG1"
{
// General
"weapontype" "All, Sniper"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_762mm"
"ammoprice" "1000"
// Knockback (module)
"knockback" "1.3"
// ZMarket (module)
"zmarketprice" "5000"
}
"AWP"
{
// General
"weapontype" "All, Sniper"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_338mag"
"ammoprice" "1000"
// Knockback (module)
"knockback" "1.8"
// ZMarket (module)
"zmarketprice" "4750"
}
"M249"
{
// General
"weapontype" "All, Machine Gun"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Weapon Ammo (core)
"ammotype" "ammo_556mm_box"
"ammoprice" "1500"
// Knockback (module)
"knockback" "1.2"
// ZMarket (module)
"zmarketprice" "5750"
}
"Knife"
{
// General
"weapontype" "All, Melee"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "no"
// Knockback (module)
"knockback" "10.0"
}
"HEGrenade"
{
// General
"weapontype" "All, Projectile"
// Restrict (core)
"restrictdefault" "no"
"toggleable" "yes"
// Knockback (module)
"knockback" "6.0"
// ZMarket (module)
"zmarketprice" "300"
}
"Flashbang"
{
// General
"weapontype" "All, Projectile"
// Restrict (core)
"restrictdefault" "yes"
"toggleable" "yes"
// ZMarket (module)
"zmarketprice" "300"
}
"Smokegrenade"
{
// General
"weapontype" "All, Projectile"
// Restrict (core)
"restrictdefault" "yes"
"toggleable" "yes"
// ZMarket (module)
"zmarketprice" "300"
}
"NVGs"
{
// General
"weapontype" "All, Equipment"
// Restrict (core)
"restrictdefault" "yes"
"toggleable" "yes"
// ZMarket (module)
"zmarketprice" "1000"
}
}

View File

@ -1,69 +0,0 @@
// Weapon Groups
// (See list of weapons in weapons.txt)
// Format
//
//
// "weapon group name" (how it appears in chat messages)
// {
// "weaponname" {} <-- To satisfy the standard format of a keyvalues file,
// without these brackets the weapon will be skipped.
// Invalid weapons are logged and skipped.
// }
//
// Notes:
//
// Invalid weapons (not in weapons.txt) will be logged in the error logs and ignored in-game
"weapongroups"
{
"Pistols"
{
"Glock" {}
"USP" {}
"P228" {}
"Deagle" {}
"Elite" {}
"Fiveseven" {}
}
"Shotguns"
{
"M3" {}
"XM1014" {}
}
"SMGs"
{
"Mac10" {}
"TMP" {}
"MP5Navy" {}
"UMP45" {}
"P90" {}
}
"Rifles"
{
"Galil" {}
"Famas" {}
"AK47" {}
"M4A1" {}
"SG552" {}
"AUG" {}
}
"Snipers"
{
"Scout" {}
"SG550" {}
"G3SG1" {}
"AWP" {}
}
"Grenades"
{
"hegrenade" {}
"flashbang" {}
"smokegrenade" {}
}
}

View File

@ -1,225 +0,0 @@
// Weapons
//
// Format
//
// "weaponname" // Name of the weapon (without weapon_ prefix)
// {
// "restrict" "no" (default) // Restricts the weapon on each map start
// "menu" "yes" (default) // Allows admins to toggle restriction with the menu
// "knockback" "1.0" (default) // The knockback multiplier for the weapon
// }
//
// Notes:
//
// This is a list of valid weapons for your server, unlisted weapons will
// be seen as invalid by the weapon restrict module.
//
// A config setting set to something other than "yes" or "no" will be assumed as "no."
//
// A missing config setting will be assumed to be its default value (documented above).
//
// Duplicate weapon entries will show up separately in restrict menu, but
// only the first one's options are used.
"weapons" // Counter-Strike: Source weapons
{
"Glock"
{
"restrict" "no"
"menu" "yes"
"knockback" "0.8"
}
"USP"
{
"restrict" "no"
"menu" "yes"
"knockback" "0.8"
}
"P228"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"Deagle"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.2"
}
"Elite"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"Fiveseven"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"M3"
{
"restrict" "no"
"menu" "yes"
"knockback" "0.8" // Remember that there are 8 pellets in 1 shot.
}
"XM1014"
{
"restrict" "no"
"menu" "yes"
"knockback" "0.8" // See above comment.
}
"Mac10"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"TMP"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"MP5Navy"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"UMP45"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"P90"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"Galil"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"Famas"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"AK47"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.2"
}
"M4A1"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.1"
}
"SG552"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.0"
}
"AUG"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.1"
}
"Scout"
{
"restrict" "no"
"menu" "yes"
"knockback" "1.5"
}
"SG550"
{
"restrict" "yes"
"menu" "yes"
"knockback" "1.3"
}
"G3SG1"
{
"restrict" "yes"
"menu" "yes"
"knockback" "1.3"
}
"AWP"
{
"restrict" "yes"
"menu" "yes"
"knockback" "1.8"
}
"M249"
{
"restrict" "yes"
"menu" "yes"
"knockback" "1.2"
}
"hegrenade"
{
"restrict" "no"
"menu" "yes"
"knockback" "6.0"
}
"flashbang"
{
"restrict" "yes"
"menu" "no"
}
"smokegrenade"
{
"restrict" "yes"
"menu" "no"
}
"Knife"
{
"restrict" "no"
"menu" "no"
"knockback" "15.0"
}
"NVGs"
{
"restrict" "yes"
"menu" "no"
}
}

View File

@ -84,8 +84,8 @@
"Config command reload syntax" "Config command reload syntax"
{ {
"#format" "{1:s},{2:s},{3:s},{4:s},{5:s},{6:s}" "#format" "{1:s},{2:s},{3:s},{4:s},{5:s}"
"en" "Syntax: zr_reloadconfig <file alias> - Reloads a config file.\n File Aliases:\n * \"{1}\"\n * \"{2}\"\n * \"{3}\"\n * \"{4}\"\n * \"{5}\"\n * \"{6}\"" "en" "Syntax: zr_reloadconfig <file alias> - Reloads a config file.\n File Aliases:\n * \"{1}\"\n * \"{2}\"\n * \"{3}\"\n * \"{4}\"\n * \"{5}\""
} }
"Config command reload invalid" "Config command reload invalid"
@ -289,46 +289,52 @@
"en" "Weapon @green\"{1}\" @defaulthas been unrestricted." "en" "Weapon @green\"{1}\" @defaulthas been unrestricted."
} }
"Restrict weapon failed" "Restrict weapon stopped"
{ {
"#format" "{1:s}" "#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaultis already restricted." "en" "Weapon @green\"{1}\" @defaultis already restricted."
} }
"Unrestrict weapon failed" "Unrestrict weapon stopped"
{ {
"#format" "{1:s}" "#format" "{1:s}"
"en" "Weapon @green\"{1}\" @default has no restrictions set." "en" "Weapon @green\"{1}\" @default has no restrictions set."
} }
"Restrict custom weapon group" "Restrict weapon type"
{ {
"#format" "{1:s},{2:s}" "#format" "{1:s}"
"en" "Weapon group @green\"{1}\" ({2}) @defaulthas been restricted." "en" "Weapons of type @green\"{1}\" @defaulthave been restricted."
} }
"Unrestrict custom weapon group" "Unrestrict weapon type"
{ {
"#format" "{1:s},{2:s}" "#format" "{1:s}"
"en" "Weapon group @green\"{1}\" ({2}) @defaulthas been unrestricted." "en" "Weapons of type @green\"{1}\" @defaulthave been unrestricted."
} }
"Restrict custom weapon group failed" "Restrict weapon type stopped"
{ {
"#format" "{1:s},{2:s}" "#format" "{1:s}"
"en" "Weapon group @green\"{1}\" ({2}) @defaultis already restricted." "en" "Weapons of type @green\"{1}\" @defaultare all already restricted."
} }
"Unrestrict custom weapon group failed" "Unrestrict weapon type stopped"
{ {
"#format" "{1:s},{2:s}" "#format" "{1:s}"
"en" "Weapon group @green\"{1}\" ({2}) @defaulthas no restrictions set." "en" "Weapons of type @green\"{1}\" @defaulthave no restrictions set."
}
"Restrict weapon untoggleable"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaultmay not have its restrictions toggled."
} }
"Weapon invalid" "Weapon invalid"
{ {
"#format" "{1:s}" "#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaultis an invalid weapon name." "en" "Weapon @green\"{1}\" @defaultis an invalid weapon (type) name."
} }
"Weapon is restricted" "Weapon is restricted"
@ -338,29 +344,28 @@
"ru" "Оружие @green{1} @default запрещено." "ru" "Оружие @green{1} @default запрещено."
} }
// Market // ZMarket
"Market title" "Market title"
{ {
"en" "Available Weapons:" "en" ""
} }
"Market rebuy" "Market rebuy"
{ {
"en" "Rebuy" "en" ""
"ru" "Купить снова"
} }
// Commands // Commands
"Weapons command restrict syntax" "Weapons command restrict syntax"
{ {
"en" "Syntax: zr_restrict <weapon> (\"weapon_\" prefix is ignored)" "en" "Restricts a weapon or a weapon type. Usage: zr_restrict <weapon|weapon type> [weapon2|weapontype2] ..."
} }
"Weapons command unrestrict syntax" "Weapons command unrestrict syntax"
{ {
"en" "Syntax: zr_unrestrict <weapon> (\"weapon_\" prefix is ignored)" "en" "Unrestricts a weapon or a weapon type. Usage: zr_unrestrict <weapon|weapon type> [weapon2|weapontype2] ..."
} }
// Menu // Menu
@ -370,56 +375,48 @@
"en" "Weapons Management" "en" "Weapons Management"
} }
"Weapons menu main toggle weapon restrict" "Weapons menu main restrict"
{ {
"en" "Toggle Weapon Restriction" "en" "Weapon Restrictions"
} }
"Weapons menu main toggle weapon group restrict" "Weapons menu main market"
{ {
"en" "Toggle Weapon Group Restriction" "en" "ZMarket"
} }
"Weapons menu main market" // Option disabled if ZMarket isn't installed "Weapons menu types title"
{ {
"en" "ZMarket Options" "en" "Weapon Restrictions\nSelect Weapon Type:"
} }
"Weapons menu weapons weapon title" "Weapons menu types type title"
{
"en" "Toggle Restrictions:\n * = restricted"
}
"Weapons menu weapons group title"
{
"en" "Access Weapon Group:\n * = Partially restricted\n ** = Fully restricted"
}
"Weapons menu weapon group title"
{ {
"#format" "{1:s}" "#format" "{1:s}"
"en" "Modify Restrictions:\n Current Weapon Group: {1}\n * = restricted" "en" "Weapon Restrictions\nWeapon Type: {1}\n[] = Restricted"
} }
"Weapons menu market title" "Weapons menu types restrict all"
{
"en" "Toggle Market Settings:"
}
"Weapons menu market toggle buyzone"
{ {
"#format" "{1:s}" "#format" "{1:s}"
"en" "Buyzone Only (Current: {1})" "en" "Restrict weapon type {1}"
} }
"Weapons menu weapon group restrict all" "Weapons menu types unrestrict all"
{ {
"en" "Restrict All Group Weapons" "#format" "{1:s}"
"en" "Unrestrict weapon type {1}\n "
} }
"Weapons menu weapon group unrestrict all" "Weapons menu zmarket title"
{ {
"en" "Unrestrict All Group Weapons" "en" "ZMarket\nSelect Setting:"
}
"Weapons menu zmarket buyzone"
{
"#format" "{1:s}"
"en" "Buyzone Only - {1}"
} }
// =========================== // ===========================
@ -556,37 +553,7 @@
"!zadmin main title" "!zadmin main title"
{ {
"en" "ZAdmin Menu:" "en" "ZAdmin\n Select Category:"
}
"!zadmin main knockbackm"
{
"en" "Modify Knockback Multiplier"
}
"!zadmin main knockback"
{
"en" "Modify Class Knockback"
}
"!zadmin main nvgs"
{
"en" "Modify Nightvision Options"
}
"!zadmin main infect"
{
"en" "Infect a Player"
}
"!zadmin main spawn"
{
"en" "Spawn All Players"
}
"!zadmin main tele"
{
"en" "ZTele Commands"
} }
"!zadmin main weapons" "!zadmin main weapons"

View File

@ -4,7 +4,7 @@
// * Zombie:Reloaded // * Zombie:Reloaded
// * // *
// * File: zombiereloaded.cfg // * File: zombiereloaded.cfg
// * Type: Core // * Type: Config
// * Description: Plugin cvar configuration. // * Description: Plugin cvar configuration.
// * // *
// * ============================================================================ // * ============================================================================

View File

@ -16,9 +16,6 @@
#include <cstrike> #include <cstrike>
#include <zrtools> #include <zrtools>
#undef REQUIRE_PLUGIN
#include <market>
#define VERSION "3.0-dev" #define VERSION "3.0-dev"
// Core includes. // Core includes.
@ -37,6 +34,7 @@
#include "zr/playerclasses/playerclasses" #include "zr/playerclasses/playerclasses"
#include "zr/weapons/weapons" #include "zr/weapons/weapons"
#include "zr/hitgroups" #include "zr/hitgroups"
#include "zr/roundstart"
#include "zr/roundend" #include "zr/roundend"
#include "zr/infect" #include "zr/infect"
#include "zr/damage" #include "zr/damage"
@ -62,9 +60,6 @@
#include "zr/jumpboost" #include "zr/jumpboost"
#include "zr/volfeatures/volfeatures" #include "zr/volfeatures/volfeatures"
// Almost replaced! :)
#include "zr/zombie"
/** /**
* Record plugin info. * Record plugin info.
*/ */
@ -106,35 +101,7 @@ public OnPluginStart()
WeaponsInit(); WeaponsInit();
SayHooksInit(); SayHooksInit();
EventInit(); EventInit();
MarketInit(); ZMarketInit();
}
/**
* Library is being removed.
*
* @param name The name of the library.
*/
public OnLibraryRemoved(const String:name[])
{
// If market is being removed, then set variable to false.
if (StrEqual(name, "market", false))
{
g_bMarket = false;
}
}
/**
* Library is being added.
*
* @param name The name of the library.
*/
public OnLibraryAdded(const String:name[])
{
// If market is being added, then set variable to true.
if (StrEqual(name, "market", false))
{
g_bMarket = true;
}
} }
/** /**
@ -165,7 +132,7 @@ public OnMapEnd()
*/ */
public OnConfigsExecuted() public OnConfigsExecuted()
{ {
// Forward event to modules. // Forward event to modules. (OnConfigsExecuted)
ConfigLoad(); ConfigLoad();
ModelsLoad(); ModelsLoad();
DownloadsLoad(); DownloadsLoad();
@ -177,6 +144,7 @@ public OnConfigsExecuted()
ClassLoad(); ClassLoad();
VolLoad(); VolLoad();
// Forward event to modules. (OnModulesLoaded)
ConfigOnModulesLoaded(); ConfigOnModulesLoaded();
ClassOnModulesLoaded(); ClassOnModulesLoaded();
} }

View File

@ -15,6 +15,24 @@
*/ */
#define ACCOUNT_CASH_MAX 16000 #define ACCOUNT_CASH_MAX 16000
/**
* Variable to store account offset value.
*/
new g_iToolsAccount;
/**
* Find account-specific offsets here.
*/
AccountOnOffsetsFound()
{
// If offset "m_iAccount" can't be found, then stop the plugin.
g_iToolsAccount = FindSendPropInfo("CCSPlayer", "m_iAccount");
if (g_iToolsAccount == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Account", "Offsets", "Offset \"CCSPlayer::m_iAccount\" was not found.");
}
}
/** /**
* Client is spawning into the game. * Client is spawning into the game.
* *

View File

@ -29,11 +29,29 @@
* @endsection * @endsection
*/ */
/**
* Variable to store antistick offset value.
*/
new g_iToolsCollisionGroup;
/** /**
* Handle to keep track of AntiStickTimer. * Handle to keep track of AntiStickTimer.
*/ */
new Handle:tAntiStick = INVALID_HANDLE; new Handle:tAntiStick = INVALID_HANDLE;
/**
* Find antistick-specific offsets here.
*/
AntiStickOnOffsetsFound()
{
// If offset "m_CollisionGroup" can't be found, then stop the plugin.
g_iToolsCollisionGroup = FindSendPropInfo("CBaseEntity", "m_CollisionGroup");
if (g_iToolsCollisionGroup == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBaseEntity::m_CollisionGroup\" was not found.");
}
}
/** /**
* Map is starting. * Map is starting.
*/ */
@ -191,4 +209,4 @@ AntiStickClientCollisionGroup(client, bool:apply = true, collisiongroup = 0)
} }
return GetEntData(client, g_iToolsCollisionGroup, 1); return GetEntData(client, g_iToolsCollisionGroup, 1);
} }

View File

@ -17,6 +17,7 @@ CommandsInit()
{ {
// Forward event to modules. (create commands) // Forward event to modules. (create commands)
ConfigOnCommandsCreate(); ConfigOnCommandsCreate();
ClassOnCommandsCreate();
WeaponsOnCommandsCreate(); WeaponsOnCommandsCreate();
VolOnCommandsCreate(); VolOnCommandsCreate();
@ -42,10 +43,6 @@ CommandsInit()
RegAdminCmd("zr_anticamp_list", Command_AnticampList, ADMFLAG_GENERIC, "List current volumes."); RegAdminCmd("zr_anticamp_list", Command_AnticampList, ADMFLAG_GENERIC, "List current volumes.");
RegConsoleCmd("zr_log_flags", Command_LogFlags, "List available logging flags."); RegConsoleCmd("zr_log_flags", Command_LogFlags, "List available logging flags.");
RegConsoleCmd("zr_class_dump", Command_ClassDump, "Dumps class data at a specified index in the specified cache. Usage: zr_class_dump <cachetype> <index|targetname>");
RegAdminCmd("zr_class_modify", Command_ClassModify, ADMFLAG_GENERIC, "Modify class data on one or more classes. Usage: zr_class_modify <classname|\"zombies\"|\"humans\"|\"admins\"> <attribute> <value> [is_multiplier]");
}*/ }*/
/*public Action:Command_Infect(client, argc) /*public Action:Command_Infect(client, argc)

View File

@ -10,6 +10,94 @@
* ============================================================================ * ============================================================================
*/ */
/*
Using config API:
-Before any of these helper functions can be used on a config file you must
"register" the module handling the data.
Example:
ConfigRegisterConfig(File_Example, Structure_List, "example");
* The first parameter of this call is the config file we want to register.
this needs to be listed in the "ConfigFile" enum in config.inc.
* The second parameter is the structure of the config file we are loading.
The supported structures are listed in the "ConfigStructure" enum in config.inc
* The last parameter is the file's alias. Or what we use to refer to the
config file from a non-developer's point of view. For example zr_config_reload
requires the file alias to identify the config file the user wants to reload.
-Next we need to define the config file's path. To do this we first need to
retrieve the path file from cvar.
Example:
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_EXAMPLE, pathexample);
* The first parameter is the cvar handle we are looking into.
* The second parameter is the string to store the path in.
* The return value is true if the file exists on the server, false if not.
If the file doesn't exist, handle it. (Print log, stop plugin, etc)
Then store it in the config file data.
Example:
ConfigSetConfigPath(File_Example, pathexample);
* The first parameter is the config file we want to set path to.
* The second parameter is the path we want to set to the config file.
-Next we load config file and prepare its nested array structure.
Example:
new bool:success = ConfigLoadConfig(File_Example, arrayExample);
* The first parameter is the config file we want to load.
* The second parameter is the array handle we want to prepare data structure in.
* The return value is true if the file was successfully loaded, false if the
config file couldn't be loaded. (Invalid data, missing quotes, brackets, etc)
-Next validate the config so far, stopping if no data was found or if ConfigLoadConfig
returned false.
-Then cache the config file data into the arrays (only for Keyvalue structures)
by iterating through the data and pushing the values into the array.
-Validate the values of the data.
-Lastly we need to set specific info to the module now that it has successfully
loaded.
Example:
ConfigSetConfigLoaded(File_Example, true);
ConfigSetConfigReloadFunc(File_Example, GetFunctionByName(GetMyHandle(), "ExampleOnConfigReload"));
ConfigSetConfigHandle(File_Example, arrayExample);
These functions will modify the config file data for other things to use.
(such as zr_config_reload)
* The first function call will set the loaded state of the config file to
true, failing to do this will cause the config module to think your
config file isn't loaded, therefore causing some undesired erroring.
* The second function sets the reload function of the config file. This
function will be called upon its config file being reloaded.
* The third function stores the array handle for use by other parts of the
module.
*/
/** /**
* The max length of any config string value. * The max length of any config string value.
*/ */
@ -22,23 +110,31 @@
#define CONFIG_FILE_ALIAS_DOWNLOADS "downloads" #define CONFIG_FILE_ALIAS_DOWNLOADS "downloads"
#define CONFIG_FILE_ALIAS_CLASSES "classes" #define CONFIG_FILE_ALIAS_CLASSES "classes"
#define CONFIG_FILE_ALIAS_WEAPONS "weapons" #define CONFIG_FILE_ALIAS_WEAPONS "weapons"
#define CONFIG_FILE_ALIAS_WEAPONGROUPS "weapongroups"
#define CONFIG_FILE_ALIAS_HITGROUPS "hitgroups" #define CONFIG_FILE_ALIAS_HITGROUPS "hitgroups"
/** /**
* @endsection * @endsection
*/ */
/**
* List of config formats used by the plugin.
*/
enum ConfigStructure
{
Structure_List, /** Config is structured as a simple list of strings. */
Structure_Keyvalue, /** Config is a keyvalue structure */
}
/** /**
* List of config files used by the plugin. * List of config files used by the plugin.
*/ */
enum ConfigFile enum ConfigFile
{ {
ConfigInvalid = -1, /** Invalid config file. */ File_Invalid = -1, /** Invalid config file. */
ConfigModels, /** <sourcemod root>/configs/zr/models.txt (default) */ File_Models, /** <sourcemod root>/configs/zr/models.txt (default) */
ConfigDownloads, /** <sourcemod root>/configs/zr/downloads.txt (default) */ File_Downloads, /** <sourcemod root>/configs/zr/downloads.txt (default) */
ConfigClasses, /** <sourcemod root>/configs/zr/playerclasses.txt (default) */ File_Classes, /** <sourcemod root>/configs/zr/playerclasses.txt (default) */
ConfigWeapons, /** <sourcemod root>/configs/zr/weapons/weapons.txt/weapongroups.txt (default) */ File_Weapons, /** <sourcemod root>/configs/zr/weapons.txt (default) */
ConfigHitgroups, /** <sourcemod root>/configs/zr/hitgroups.txt (default) */ File_Hitgroups, /** <sourcemod root>/configs/zr/hitgroups.txt (default) */
} }
/** /**
@ -46,11 +142,12 @@ enum ConfigFile
*/ */
enum ConfigData enum ConfigData
{ {
bool:ConfigLoaded, /** True if config is loaded, false if not. */ bool: Data_Loaded, /** True if config is loaded, false if not. */
Function:ConfigReloadFunc, /** Function to call to reload config. */ ConfigStructure: Data_Structure, /** Format of the config */
Handle:ConfigHandle, /** Handle of the config file. */ Function: Data_ReloadFunc, /** Function to call to reload config. */
String:ConfigPath[PLATFORM_MAX_PATH], /** Full path to config file. */ Handle: Data_Handle, /** Handle of the config file. */
String:ConfigAlias[CONFIG_MAX_LENGTH], /** Config file alias, used for client interaction. */ String: Data_Path[PLATFORM_MAX_PATH], /** Full path to config file. */
String: Data_Alias[CONFIG_MAX_LENGTH], /** Config file alias, used for client interaction. */
} }
/** /**
@ -61,32 +158,22 @@ new g_ConfigData[ConfigFile][ConfigData];
/** /**
* Actions to use when working on key/values. * Actions to use when working on key/values.
*/ */
enum ConfigKeyvalueAction enum ConfigKvAction
{ {
ConfigKVCreate, /** Create a key. */ KvAction_Create, /** Create a key. */
ConfigKVDelete, /** Delete a key. */ KvAction_KVDelete, /** Delete a key. */
ConfigKVSet, /** Modify setting of a key. */ KvAction_KVSet, /** Modify setting of a key. */
ConfigKVGet, /** Get setting of a key. */ KvAction_KVGet, /** Get setting of a key. */
} }
/**
* @section Global data handle initializations.
*/
new Handle:arrayModelsList = INVALID_HANDLE;
new Handle:arrayDownloadsList = INVALID_HANDLE;
new Handle:kvClassData = INVALID_HANDLE;
new Handle:kvWeapons = INVALID_HANDLE;
new Handle:kvWeaponGroups = INVALID_HANDLE;
new Handle:kvHitgroups = INVALID_HANDLE;
/** /**
* Create commands related to config here. * Create commands related to config here.
*/ */
ConfigOnCommandsCreate() ConfigOnCommandsCreate()
{ {
// Create config admin commands. // Create config admin commands.
RegAdminCmd("zr_reloadconfig", ConfigReloadCommand, ADMFLAG_GENERIC, "zr_reloadconfig <file alias> - Reloads a config file."); RegAdminCmd("zr_config_reload", ConfigReloadCommand, ADMFLAG_GENERIC, "Reloads a config file. Usage: zr_config_reload <file alias>");
RegAdminCmd("zr_reloadconfigall", ConfigReloadAllCommand, ADMFLAG_GENERIC, "zr_reloadconfigall - Reloads all config files."); RegAdminCmd("zr_config_reloadall", ConfigReloadAllCommand, ADMFLAG_GENERIC, "Reloads all config files. Usage: zr_config_reloadall");
} }
/** /**
@ -157,20 +244,20 @@ ConfigOnModulesLoaded()
/** /**
* Used by modules that rely on configs to register their config file info. * Used by modules that rely on configs to register their config file info.
* (Don't forget to set 'loaded' to 'true' (ConfigSetConfigLoaded) in config load function)
* *
* @param file Config file entry to register. * @param file Config file entry to register.
* @param loaded True if the config should be loaded, false if not. * @param alias Config file alias, used for client interaction.
* @param path (Optional) Full path to config file.
* @param alias (Optional) Config file alias, used for client interaction.
*/ */
stock ConfigRegisterConfig(ConfigFile:file, bool:loaded, Function:reloadfunc, Handle:filehandle = INVALID_HANDLE, const String:path[] = "", const String:alias[] = "") stock ConfigRegisterConfig(ConfigFile:file, ConfigStructure:structure, const String:alias[] = "")
{ {
// Copy file info to data container. // Copy file info to data container.
g_ConfigData[file][ConfigLoaded] = loaded; g_ConfigData[file][Data_Loaded] = false;
g_ConfigData[file][ConfigHandle] = filehandle; g_ConfigData[file][Data_Structure] = structure;
g_ConfigData[file][ConfigReloadFunc] = reloadfunc; g_ConfigData[file][Data_Handle] = INVALID_HANDLE;
strcopy(g_ConfigData[file][ConfigPath], PLATFORM_MAX_PATH, path); g_ConfigData[file][Data_ReloadFunc] = INVALID_FUNCTION;
strcopy(g_ConfigData[file][ConfigAlias], CONFIG_MAX_LENGTH, alias); strcopy(g_ConfigData[file][Data_Path], PLATFORM_MAX_PATH, "");
strcopy(g_ConfigData[file][Data_Alias], CONFIG_MAX_LENGTH, alias);
} }
/** /**
@ -182,7 +269,19 @@ stock ConfigRegisterConfig(ConfigFile:file, bool:loaded, Function:reloadfunc, Ha
stock ConfigSetConfigLoaded(ConfigFile:config, bool:loaded) stock ConfigSetConfigLoaded(ConfigFile:config, bool:loaded)
{ {
// Set load state. // Set load state.
g_ConfigData[config][ConfigLoaded] = loaded; g_ConfigData[config][Data_Loaded] = loaded;
}
/**
* Set the structure type of a config file entry.
*
* @param config Config file to set structure type of.
* @param structure Structure to set as.
*/
stock ConfigSetConfigStructure(ConfigFile:config, ConfigStructure:structure)
{
// Set load state.
g_ConfigData[config][Data_Structure] = structure;
} }
/** /**
@ -194,7 +293,7 @@ stock ConfigSetConfigLoaded(ConfigFile:config, bool:loaded)
stock ConfigSetConfigReloadFunc(ConfigFile:config, Function:reloadfunc) stock ConfigSetConfigReloadFunc(ConfigFile:config, Function:reloadfunc)
{ {
// Set reload function. // Set reload function.
g_ConfigData[config][ConfigReloadFunc] = reloadfunc; g_ConfigData[config][Data_ReloadFunc] = reloadfunc;
} }
/** /**
@ -206,7 +305,7 @@ stock ConfigSetConfigReloadFunc(ConfigFile:config, Function:reloadfunc)
stock ConfigSetConfigHandle(ConfigFile:config, Handle:file) stock ConfigSetConfigHandle(ConfigFile:config, Handle:file)
{ {
// Set file handle. // Set file handle.
g_ConfigData[config][ConfigHandle] = file; g_ConfigData[config][Data_Handle] = file;
} }
/** /**
@ -218,7 +317,7 @@ stock ConfigSetConfigHandle(ConfigFile:config, Handle:file)
stock ConfigSetConfigPath(ConfigFile:config, const String:path[]) stock ConfigSetConfigPath(ConfigFile:config, const String:path[])
{ {
// Set config file path. // Set config file path.
strcopy(g_ConfigData[config][ConfigPath], PLATFORM_MAX_PATH, path); strcopy(g_ConfigData[config][Data_Path], PLATFORM_MAX_PATH, path);
} }
/** /**
@ -230,7 +329,7 @@ stock ConfigSetConfigPath(ConfigFile:config, const String:path[])
stock ConfigSetConfigAlias(ConfigFile:config, const String:alias[]) stock ConfigSetConfigAlias(ConfigFile:config, const String:alias[])
{ {
// Set config alias. // Set config alias.
strcopy(g_ConfigData[config][ConfigAlias], CONFIG_MAX_LENGTH, alias); strcopy(g_ConfigData[config][Data_Alias], CONFIG_MAX_LENGTH, alias);
} }
/** /**
@ -242,7 +341,19 @@ stock ConfigSetConfigAlias(ConfigFile:config, const String:alias[])
stock bool:ConfigIsConfigLoaded(ConfigFile:config) stock bool:ConfigIsConfigLoaded(ConfigFile:config)
{ {
// Return load status. // Return load status.
return g_ConfigData[config][ConfigLoaded]; return g_ConfigData[config][Data_Loaded];
}
/**
* Returns config's structure type.
*
* @param config Config file to get structure type of.
* @return Config structure type.
*/
stock ConfigStructure:ConfigGetConfigStructure(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][Data_Structure];
} }
/** /**
@ -254,7 +365,7 @@ stock bool:ConfigIsConfigLoaded(ConfigFile:config)
stock Function:ConfigGetConfigReloadFunc(ConfigFile:config) stock Function:ConfigGetConfigReloadFunc(ConfigFile:config)
{ {
// Return load status. // Return load status.
return g_ConfigData[config][ConfigReloadFunc]; return g_ConfigData[config][Data_ReloadFunc];
} }
/** /**
@ -266,7 +377,7 @@ stock Function:ConfigGetConfigReloadFunc(ConfigFile:config)
stock Handle:ConfigGetConfigHandle(ConfigFile:config) stock Handle:ConfigGetConfigHandle(ConfigFile:config)
{ {
// Return load status. // Return load status.
return g_ConfigData[config][ConfigHandle]; return g_ConfigData[config][Data_Handle];
} }
/** /**
@ -277,7 +388,7 @@ stock Handle:ConfigGetConfigHandle(ConfigFile:config)
stock ConfigGetConfigPath(ConfigFile:config, String:path[], maxlen) stock ConfigGetConfigPath(ConfigFile:config, String:path[], maxlen)
{ {
// Copy path to return string. // Copy path to return string.
strcopy(path, maxlen, g_ConfigData[config][ConfigPath]); strcopy(path, maxlen, g_ConfigData[config][Data_Path]);
} }
/** /**
@ -288,7 +399,131 @@ stock ConfigGetConfigPath(ConfigFile:config, String:path[], maxlen)
stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen) stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen)
{ {
// Copy alias to return string. // Copy alias to return string.
strcopy(alias, maxlen, g_ConfigData[config][ConfigAlias]); strcopy(alias, maxlen, g_ConfigData[config][Data_Alias]);
}
/**
* Loads a config file and sets up a nested array type data storage.
*
* @param config The config file to load.
* @param arrayConfig Handle of the main array containing file data.
* @return True if file was loaded successfuly, false otherwise.
*/
stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig)
{
// Get config's structure.
new ConfigStructure:structure = ConfigGetConfigStructure(config);
// Get config's alias
decl String:configalias[CONFIG_MAX_LENGTH];
ConfigGetConfigAlias(config, configalias, sizeof(configalias));
// Get config's file path.
decl String:configpath[PLATFORM_MAX_PATH];
ConfigGetConfigPath(config, configpath, sizeof(configpath));
// If handle is still open, then close it before creating a new one.
if (arrayConfig == INVALID_HANDLE)
{
// Create array in handle.
arrayConfig = CreateArray(CONFIG_MAX_LENGTH);
}
switch(structure)
{
case Structure_List:
{
// Open file.
new Handle:hFile;
new success = ConfigOpenConfigFile(config, hFile);
// If config file failed to open, then stop.
if (!success)
{
return false;
}
// Clear out array.
ClearArray(arrayConfig);
decl String:line[PLATFORM_MAX_PATH];
while(!IsEndOfFile(hFile))
{
// Get current line text.
ReadFileLine(hFile, line, sizeof(line));
// If line contains a ";", then stop.
if (StrContains(line, ";") > -1)
{
continue;
}
// Cut out comments at the end of a line.
if (StrContains(line, "//") > -1)
{
SplitString(line, "//", line, sizeof(line));
}
// Trim off whitespace.
TrimString(line);
// If line is empty, then stop.
if (!line[0])
{
continue;
}
// Push line into array.
PushArrayString(arrayConfig, line);
}
// We're done this file, so now we can destory it from memory.
CloseHandle(hFile);
return true;
}
case Structure_Keyvalue:
{
// Open file.
new Handle:hKeyvalue;
new success = ConfigOpenConfigFile(config, hKeyvalue);
// If config file failed to open, then stop.
if (!success)
{
return false;
}
// Destroy all old data.
ConfigClearKvArray(arrayConfig);
if (KvGotoFirstSubKey(hKeyvalue))
{
do
{
// Create new array to store information for config entry.
new Handle:arrayConfigEntry = CreateArray(CONFIG_MAX_LENGTH);
// Push the key name into the config entry's array.
decl String:keyname[CONFIG_MAX_LENGTH];
KvGetSectionName(hKeyvalue, keyname, sizeof(keyname));
PushArrayString(arrayConfigEntry, keyname); // Index: 0
// Store this handle in the main array.
PushArrayCell(arrayConfig, arrayConfigEntry);
} while(KvGotoNextKey(hKeyvalue));
}
// We're done this file for now, so now we can destory it from memory.
CloseHandle(hKeyvalue);
return true;
}
}
return false;
} }
/** /**
@ -297,7 +532,7 @@ stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen)
* @param config The config file entry to reload. * @param config The config file entry to reload.
* @return True if the config is loaded, false if not. * @return True if the config is loaded, false if not.
*/ */
stock bool:ConfigReloadFile(ConfigFile:config) stock bool:ConfigReloadConfig(ConfigFile:config)
{ {
// If file isn't loaded, then stop. // If file isn't loaded, then stop.
new bool:loaded = ConfigIsConfigLoaded(config); new bool:loaded = ConfigIsConfigLoaded(config);
@ -309,6 +544,7 @@ stock bool:ConfigReloadFile(ConfigFile:config)
// Call reload function // Call reload function
new Function:reloadfunc = ConfigGetConfigReloadFunc(config); new Function:reloadfunc = ConfigGetConfigReloadFunc(config);
// This should never be true unless someone has tampered with the code.
if (reloadfunc == INVALID_FUNCTION) if (reloadfunc == INVALID_FUNCTION)
{ {
// Get config alias. // Get config alias.
@ -323,12 +559,169 @@ stock bool:ConfigReloadFile(ConfigFile:config)
// Call reload function. // Call reload function.
Call_StartFunction(GetMyHandle(), reloadfunc); Call_StartFunction(GetMyHandle(), reloadfunc);
Call_PushCell(config);
Call_Finish(); Call_Finish();
return true; return true;
} }
/**
* Opens a config file with appropriate method.
*
* @param config The config file.
* @param structure The structure of the config file.
* @param hConfig The handle of the opened file.
*/
stock bool:ConfigOpenConfigFile(ConfigFile:config, &Handle:hConfig)
{
// Get config's structure
new ConfigStructure:structure = ConfigGetConfigStructure(config);
// Get config's file path.
decl String:configpath[PLATFORM_MAX_PATH];
ConfigGetConfigPath(config, configpath, sizeof(configpath));
// Get config's alias
decl String:configalias[CONFIG_MAX_LENGTH];
ConfigGetConfigAlias(config, configalias, sizeof(configalias));
switch(structure)
{
case Structure_List:
{
// Open file.
hConfig = OpenFile(configpath, "r");
// If file couldn't be opened, then stop.
if (hConfig == INVALID_HANDLE)
{
return false;
}
return true;
}
case Structure_Keyvalue:
{
hConfig = CreateKeyValues(configalias);
return FileToKeyValues(hConfig, configpath);
}
}
return false;
}
/**
* Creates, deletes, sets, or gets any key/setting of any ZR config keyvalue file in memory.
* Only use when interacting with a command or manipulating single keys/values,
* using this function everywhere would be EXTREMELY inefficient.
*
* @param config Config file to modify.
* @param action Action to perform on keyvalue tree. (see enum ConfigKeyvalueAction)
* @param keys Array containing keys to traverse into.
* @param keysMax The size of the 'keys' array.
* @param setting (Optional) The name of the setting to modify.
* @param value (Optional) The new value to set.
* @param maxlen (Optional) The maxlength of the retrieved value.
* @return True if the change was made successfully, false otherwise.
*/
stock bool:ConfigKeyvalueTreeSetting(ConfigFile:config, ConfigKvAction:action = KvAction_Create, const String:keys[][], keysMax, const String:setting[] = "", String:value[] = "", maxlen = 0)
{
// Get config file's structure.
new ConfigStructure:structure = ConfigGetConfigStructure(config);
// If the config is any other structure beside keyvalue, then stop.
if (structure != Structure_Keyvalue)
{
return false;
}
// Retrieve handle of the keyvalue tree.
new Handle:hConfig;
new bool:success = ConfigOpenConfigFile(config, hConfig);
// If the file couldn't be opened, then stop.
if (!success)
{
return false;
}
// Rewind keyvalue tree.
KvRewind(hConfig);
// x = keys index.
// Traverse into the keygroup, stop if it fails.
for (new x = 0; x < keysMax; x++)
{
// If key is empty, then break the loop.
if (!keys[x][0])
{
break;
}
// Try to jump to next level in the transversal stack, create key if specified.
new bool:exists = KvJumpToKey(hConfig, keys[x], (action == KvAction_Create));
// If exists is false, then stop.
if (!exists)
{
// Key doesn't exist.
return false;
}
}
switch(action)
{
case KvAction_Create:
{
if (!setting[0] || !value[0])
{
// We created the key already, so return true.
return true;
}
// Set new value.
KvSetString(hConfig, setting, value);
}
case KvAction_Delete:
{
// Return deletion result.
return KvDeleteKey(hConfig, setting);
}
case KvAction_Set:
{
// Set new value.
KvSetString(hConfig, setting, value);
}
case KvAction_Get:
{
// Get current value.
KvGetString(hConfig, setting, value, maxlen);
}
}
// We successfully set or got the value.
return true;
}
/**
* Destroy all array handles within an array, and clear main array.
*
* @param arrayKv The array converted from a keyvalue structure.
*/
ConfigClearKvArray(Handle:arrayKv)
{
// x = array index
new size = GetArraySize(arrayKv);
for (new x = 0; x < size; x++)
{
// Destroy nested arrays.
new Handle:arrayKvKey = GetArrayCell(arrayKv, x);
CloseHandle(arrayKvKey);
}
// Now that all data within has been destroyed, we can clear the main array.
ClearArray(arrayKv);
}
/** /**
* Load config file. * Load config file.
* *
@ -374,94 +767,11 @@ stock ConfigFile:ConfigAliasToConfigFile(const String:alias[])
} }
// Invalid config file. // Invalid config file.
return ConfigInvalid; return File_Invalid;
} }
/** /**
* Creates, deletes, sets, or gets any key/setting of any ZR config keyvalue file in memory. * Command callback (zr_config_reload)
* Only use when interacting with a command or manipulating single keys/values,
* using this function everywhere would be EXTREMELY inefficient.
*
* @param config Config index of config to modify. (see CONFIG_FILE_* defines)
* @param action Action to perform on keyvalue tree. (see enum ConfigKeyvalueAction)
* @param keys Array containing keys to traverse into.
* @param keysMax The size of the 'keys' array.
* @param setting (Optional) The name of the setting to modify.
* @param value (Optional) The new value to set.
* @param maxlen (Optional) The maxlength of the gotten value.
* @return True if the change was made successfully, false otherwise.
*/
stock bool:ConfigKeyvalueTreeSetting(config, ConfigKeyvalueAction:action = ConfigKVCreate, const String:keys[][], keysMax, const String:setting[] = "", String:value[] = "", maxlen = 0)
{
// Retrieve handle of the keyvalue tree.
new Handle:hConfig = ConfigGetConfigHandle(config);
// If handle is invalid, then stop.
if (hConfig == INVALID_HANDLE)
{
return false;
}
// Rewind keyvalue tree.
KvRewind(hConfig);
// x = keys index.
// Traverse into the keygroup, stop if it fails.
for (new x = 0; x < keysMax; x++)
{
// If key is empty, then break the loop.
if (!keys[x][0])
{
break;
}
// Try to jump to next level in the transversal stack, create key if specified.
new bool:exists = KvJumpToKey(hConfig, keys[x], (action == Create));
// If exists is false, then stop.
if (!exists)
{
// Key doesn't exist.
return false;
}
}
switch(action)
{
case ConfigKVCreate:
{
if (!setting[0] || !value[0])
{
// We created the key already, so return true.
return true;
}
// Set new value.
KvSetString(hConfig, setting, value);
}
case ConfigKVDelete:
{
// Return deletion result.
return KvDeleteKey(hConfig, setting);
}
case ConfigKVSet:
{
// Set new value.
KvSetString(hConfig, setting, value);
}
case ConfigKVGet:
{
// Get current value.
KvGetString(hConfig, setting, value, maxlen);
}
}
// We successfully set or got the value.
return true;
}
/**
* Command callback (zr_reloadconfig)
* Reloads a config file and forwards event to modules. * Reloads a config file and forwards event to modules.
* *
* @param client The client index. * @param client The client index.
@ -472,7 +782,7 @@ public Action:ConfigReloadCommand(client, argc)
// If not enough arguments given, then stop. // If not enough arguments given, then stop.
if (argc < 1) if (argc < 1)
{ {
TranslationReplyToCommand(client, "Config command reload syntax", CONFIG_FILE_ALIAS_MODELS, CONFIG_FILE_ALIAS_DOWNLOADS, CONFIG_FILE_ALIAS_CLASSES, CONFIG_FILE_ALIAS_WEAPONS, CONFIG_FILE_ALIAS_WEAPONGROUPS, CONFIG_FILE_ALIAS_HITGROUPS); TranslationReplyToCommand(client, "Config command reload syntax", CONFIG_FILE_ALIAS_MODELS, CONFIG_FILE_ALIAS_DOWNLOADS, CONFIG_FILE_ALIAS_CLASSES, CONFIG_FILE_ALIAS_WEAPONS, CONFIG_FILE_ALIAS_HITGROUPS);
return Plugin_Handled; return Plugin_Handled;
} }
@ -482,14 +792,14 @@ public Action:ConfigReloadCommand(client, argc)
// If alias is invalid, then stop. // If alias is invalid, then stop.
new ConfigFile:config = ConfigAliasToConfigFile(arg1); new ConfigFile:config = ConfigAliasToConfigFile(arg1);
if (config == ConfigInvalid) if (config == File_Invalid)
{ {
TranslationReplyToCommand(client, "Config command reload invalid", arg1); TranslationReplyToCommand(client, "Config command reload invalid", arg1);
return Plugin_Handled; return Plugin_Handled;
} }
// Reload config file. // Reload config file.
new bool:loaded = ConfigReloadFile(config); new bool:loaded = ConfigReloadConfig(config);
// Get config file path. // Get config file path.
decl String:path[PLATFORM_MAX_PATH]; decl String:path[PLATFORM_MAX_PATH];
@ -506,7 +816,7 @@ public Action:ConfigReloadCommand(client, argc)
} }
/** /**
* Command callback (zr_reloadconfigall) * Command callback (zr_config_reloadall)
* Reloads all config files and forwards event to all modules. * Reloads all config files and forwards event to all modules.
* *
* @param client The client index. * @param client The client index.
@ -523,7 +833,7 @@ public Action:ConfigReloadAllCommand(client, argc)
for (new x = 0; x < sizeof(g_ConfigData); x++) for (new x = 0; x < sizeof(g_ConfigData); x++)
{ {
// Reload config file. // Reload config file.
new bool:successful = ConfigReloadFile(ConfigFile:x); new bool:successful = ConfigReloadConfig(ConfigFile:x);
// Get config's alias. // Get config's alias.
ConfigGetConfigAlias(ConfigFile:x, configalias, sizeof(configalias)); ConfigGetConfigAlias(ConfigFile:x, configalias, sizeof(configalias));
@ -539,71 +849,13 @@ public Action:ConfigReloadAllCommand(client, argc)
} }
} }
/**
* Iterate through a file and store each line in an array.
*
* @param path Path to the file to iterate through.
* @return The handle of the array, don't forget to call CloseHandle
* on it when finished!
*/
Handle:ConfigLinesToArray(const String:path[])
{
new Handle:arrayLines = CreateArray(PLATFORM_MAX_PATH);
decl String:line[PLATFORM_MAX_PATH];
// Open file.
new Handle:hFile = OpenFile(path, "r");
// If file couldn't be opened, then stop.
if (hFile == INVALID_HANDLE)
{
return INVALID_HANDLE;
}
while(!IsEndOfFile(hFile))
{
// Get current line text.
ReadFileLine(hFile, line, sizeof(line));
// If line contains a ";", then stop.
if (StrContains(line, ";") > -1)
{
continue;
}
// Cut out comments at the end of a line.
if (StrContains(line, "//") > -1)
{
SplitString(line, "//", line, sizeof(line));
}
// Trim off whitespace.
TrimString(line);
// If line is empty, then stop.
if (!line[0])
{
continue;
}
// Push line into array.
PushArrayString(arrayLines, line);
}
// Close file handle.
CloseHandle(hFile);
// Return array handle.
return arrayLines;
}
/** /**
* Converts string of "yes" or "no" to a boolean value. * Converts string of "yes" or "no" to a boolean value.
* *
* @param option "yes" or "no" string to be converted. * @param option "yes" or "no" string to be converted.
* @return True if string is "yes", false otherwise. * @return True if string is "yes", false otherwise.
*/ */
bool:ConfigSettingToBool(const String:option[]) stock bool:ConfigSettingToBool(const String:option[])
{ {
// If option is equal to "yes," then return true. // If option is equal to "yes," then return true.
if (StrEqual(option, "yes", false)) if (StrEqual(option, "yes", false))
@ -620,9 +872,9 @@ bool:ConfigSettingToBool(const String:option[])
* *
* @param bOption True/false value to be converted to "yes"/"no", respectively. * @param bOption True/false value to be converted to "yes"/"no", respectively.
* @param option Destination string buffer to store "yes" or "no" in. * @param option Destination string buffer to store "yes" or "no" in.
* @param maxlen Length of destination string buffer (can't be more than 4). * @param maxlen Length of destination string buffer (wont't be more than 4).
*/ */
ConfigBoolToSetting(bool:bOption, String:option[], maxlen) stock ConfigBoolToSetting(bool:bOption, String:option[], maxlen)
{ {
// If option is true, then copy "yes" to return string. // If option is true, then copy "yes" to return string.
if (bOption) if (bOption)
@ -635,3 +887,11 @@ ConfigBoolToSetting(bool:bOption, String:option[], maxlen)
strcopy(option, maxlen, "no"); strcopy(option, maxlen, "no");
} }
} }
stock bool:ConfigKvGetStringBool(Handle:kv, const String:key[], const String:defaultvalue[] = "yes")
{
decl String:value[CONFIG_MAX_LENGTH];
KvGetString(kv, key, value, sizeof(value), defaultvalue);
return ConfigSettingToBool(value);
}

View File

@ -38,7 +38,6 @@ enum CvarsList
Handle:CVAR_CONFIG_PATH_DOWNLOADS, Handle:CVAR_CONFIG_PATH_DOWNLOADS,
Handle:CVAR_CONFIG_PATH_CLASSES, Handle:CVAR_CONFIG_PATH_CLASSES,
Handle:CVAR_CONFIG_PATH_WEAPONS, Handle:CVAR_CONFIG_PATH_WEAPONS,
Handle:CVAR_CONFIG_PATH_WEAPONGROUPS,
Handle:CVAR_CONFIG_PATH_HITGROUPS, Handle:CVAR_CONFIG_PATH_HITGROUPS,
Handle:CVAR_CLASSES_SPAWN, Handle:CVAR_CLASSES_SPAWN,
Handle:CVAR_CLASSES_RANDOM, Handle:CVAR_CLASSES_RANDOM,
@ -51,6 +50,7 @@ enum CvarsList
Handle:CVAR_CLASSES_OVERLAY_DEFAULT, Handle:CVAR_CLASSES_OVERLAY_DEFAULT,
Handle:CVAR_WEAPONS, Handle:CVAR_WEAPONS,
Handle:CVAR_WEAPONS_RESTRICT, Handle:CVAR_WEAPONS_RESTRICT,
Handle:CVAR_WEAPONS_ZMARKET,
Handle:CVAR_WEAPONS_ZMARKET_BUYZONE, Handle:CVAR_WEAPONS_ZMARKET_BUYZONE,
Handle:CVAR_HITGROUPS, Handle:CVAR_HITGROUPS,
Handle:CVAR_DAMAGE_HITGROUPS, Handle:CVAR_DAMAGE_HITGROUPS,
@ -210,9 +210,8 @@ CvarsCreate()
// =========================== // ===========================
g_hCvarsList[CVAR_CONFIG_PATH_MODELS] = CreateConVar("zr_config_path_models", "configs/zr/models.txt", "Path, relative to root sourcemod directory, to models config file."); g_hCvarsList[CVAR_CONFIG_PATH_MODELS] = CreateConVar("zr_config_path_models", "configs/zr/models.txt", "Path, relative to root sourcemod directory, to models config file.");
g_hCvarsList[CVAR_CONFIG_PATH_DOWNLOADS] = CreateConVar("zr_config_path_downloads", "configs/zr/downloads.txt", "Path, relative to root sourcemod directory, to downloads file."); g_hCvarsList[CVAR_CONFIG_PATH_DOWNLOADS] = CreateConVar("zr_config_path_downloads", "configs/zr/downloads.txt", "Path, relative to root sourcemod directory, to downloads file.");
g_hCvarsList[CVAR_CONFIG_PATH_CLASSES] = CreateConVar("zr_config_path_playerclasses", "configs/zr/playerclasses.txt", "Path, relative to root sourcemod directory, to playerclasses config file."); g_hCvarsList[CVAR_CONFIG_PATH_CLASSES] = CreateConVar("zr_config_path_playerclasses", "configs/zr/playerclasses.txt", "Path, relative to root sourcemod directory, to playerclasses config file.");
g_hCvarsList[CVAR_CONFIG_PATH_WEAPONS] = CreateConVar("zr_config_path_weapons", "configs/zr/weapons/weapons.txt", "Path, relative to root sourcemod directory, to weapons config file."); g_hCvarsList[CVAR_CONFIG_PATH_WEAPONS] = CreateConVar("zr_config_path_weapons", "configs/zr/weapons.txt", "Path, relative to root sourcemod directory, to weapons config file.");
g_hCvarsList[CVAR_CONFIG_PATH_WEAPONGROUPS] = CreateConVar("zr_config_path_weapongroups", "configs/zr/weapons/weapongroups.txt", "Path, relative to root sourcemod directory, to weapongroups config file.");
g_hCvarsList[CVAR_CONFIG_PATH_HITGROUPS] = CreateConVar("zr_config_path_hitgroups", "configs/zr/hitgroups.txt", "Path, relative to root sourcemod directory, to hitgroups config file."); g_hCvarsList[CVAR_CONFIG_PATH_HITGROUPS] = CreateConVar("zr_config_path_hitgroups", "configs/zr/hitgroups.txt", "Path, relative to root sourcemod directory, to hitgroups config file.");
@ -260,8 +259,9 @@ CvarsCreate()
// Restrict // Restrict
g_hCvarsList[CVAR_WEAPONS_RESTRICT] = CreateConVar("zr_weapons_restrict", "1", "Enable weapon restriction module, disabling this will disable weapon restriction commands."); g_hCvarsList[CVAR_WEAPONS_RESTRICT] = CreateConVar("zr_weapons_restrict", "1", "Enable weapon restriction module, disabling this will disable weapon restriction commands.");
// Market Handler // ZMarket
g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE] = CreateConVar("zr_weapons_zmarket_buyzone", "1", "Requires player to be inside a buyzone to use ZMarket."); g_hCvarsList[CVAR_WEAPONS_ZMARKET] = CreateConVar("zr_weapons_zmarket", "1", "Allow player to buy from a list of weapons in the weapons config.");
g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE] = CreateConVar("zr_weapons_zmarket_buyzone", "1", "Requires player to be inside a buyzone to use ZMarket. [Dependency: zr_weapons_zmarket]");
// =========================== // ===========================

View File

@ -48,7 +48,7 @@ DamageOnCommandsHook()
// Explode string into array indexes. // Explode string into array indexes.
new cmdcount = ExplodeString(suicidecmds, ", ", arrayCmds, DAMAGE_SUICIDE_MAX_CMDS, DAMAGE_SUICIDE_MAX_LENGTH); new cmdcount = ExplodeString(suicidecmds, ", ", arrayCmds, DAMAGE_SUICIDE_MAX_CMDS, DAMAGE_SUICIDE_MAX_LENGTH);
// x = array index. // x = Array index.
// arrayCmds[x] = suicide command. // arrayCmds[x] = suicide command.
for (new x = 0; x <= cmdcount - 1; x++) for (new x = 0; x <= cmdcount - 1; x++)
{ {
@ -147,7 +147,16 @@ public ZRTools_Action:DamageTraceAttack(client, inflictor, attacker, Float:damag
} }
// If damage is disabled for this hitgroup, then stop. // If damage is disabled for this hitgroup, then stop.
new bool:candamage = HitgroupsCanDamageHitgroup(hitgroup); new index = HitgroupToIndex(hitgroup);
// If index can't be found, then allow damage.
if (index == -1)
{
// Allow damage.
return ZRTools_Continue;
}
new bool:candamage = HitgroupsCanDamage(index);
if (!candamage) if (!candamage)
{ {
// Stop bullet from hurting client. // Stop bullet from hurting client.

View File

@ -12,43 +12,38 @@
/** /**
* Array that stores a list of downloadable files. * Array that stores a list of downloadable files.
*
* @redir config.inc
*/ */
new Handle:arrayDownloads = INVALID_HANDLE;
/** /**
* Prepare all model/download data. * Prepare all model/download data.
*/ */
DownloadsLoad() DownloadsLoad()
{ {
// Register config file.
ConfigRegisterConfig(File_Downloads, Structure_List, CONFIG_FILE_ALIAS_DOWNLOADS);
// Get downloads file path. // Get downloads file path.
decl String:pathdownloads[PLATFORM_MAX_PATH]; decl String:pathdownloads[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_DOWNLOADS, pathdownloads); new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_DOWNLOADS, pathdownloads);
// Register config info. // If file doesn't exist, then log and stop.
ConfigRegisterConfig(ConfigDownloads, false, GetFunctionByName(GetMyHandle(), "DownloadsOnConfigReload"), _, pathdownloads, CONFIG_FILE_ALIAS_DOWNLOADS);
// If file doesn't exist, then log.
if (!exists) if (!exists)
{ {
// Log error, then stop. // Log failure and stop plugin.
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Downloads", "Config Validation", "Missing downloads file: \"%s\"", pathdownloads); LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Downloads", "Config Validation", "Fatal Error: Missing downloads file: \"%s\"", pathdownloads);
return;
} }
// If download array exists, then destroy it. // Set the path to the config file.
if (arrayDownloadsList != INVALID_HANDLE) ConfigSetConfigPath(File_Downloads, pathdownloads);
{
CloseHandle(arrayDownloadsList);
}
arrayDownloadsList = ConfigLinesToArray(pathdownloads); // Load config from file and create array structure.
new bool:success = ConfigLoadConfig(File_Downloads, arrayDownloads);
// If array couldn't be created, then fail. // Unexpected error, stop plugin.
if (arrayDownloadsList == INVALID_HANDLE) if (!success)
{ {
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Downloads", "Config Validation", "Error parsing \"%s\"", pathdownloads); LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Downloads", "Config Validation", "Fatal Error: Unexpected error encountered loading: %s", pathdownloads);
} }
new downloadcount; new downloadcount;
@ -56,19 +51,19 @@ DownloadsLoad()
decl String:downloadpath[PLATFORM_MAX_PATH]; decl String:downloadpath[PLATFORM_MAX_PATH];
new downloads = downloadcount = GetArraySize(arrayDownloadsList); new downloads = downloadcount = GetArraySize(arrayDownloads);
// x = download array index. // x = download array index.
for (new x = 0; x < downloads; x++) for (new x = 0; x < downloads; x++)
{ {
// Get base model path (rawline in models.txt) // Get download path
GetArrayString(arrayDownloadsList, x, downloadpath, sizeof(downloadpath)); GetArrayString(arrayDownloads, x, downloadpath, sizeof(downloadpath));
// If file doesn't exist, then remove, log, and stop. // If file doesn't exist, then remove, log, and stop.
if (!FileExists(downloadpath)) if (!FileExists(downloadpath))
{ {
// Remove client from array. // Remove client from array.
RemoveFromArray(arrayDownloadsList, x); RemoveFromArray(arrayDownloads, x);
// Subtract one from count. // Subtract one from count.
downloads--; downloads--;
@ -91,8 +86,9 @@ DownloadsLoad()
LogPrintToLog(LOG_FORMAT_TYPE_NORMAL, "Downloads", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", downloadcount, downloadvalidcount, downloadcount - downloadvalidcount); LogPrintToLog(LOG_FORMAT_TYPE_NORMAL, "Downloads", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", downloadcount, downloadvalidcount, downloadcount - downloadvalidcount);
// Set config data. // Set config data.
ConfigSetConfigLoaded(ConfigDownloads, true); ConfigSetConfigLoaded(File_Downloads, true);
ConfigSetConfigHandle(ConfigDownloads, arrayDownloadsList); ConfigSetConfigReloadFunc(File_Downloads, GetFunctionByName(GetMyHandle(), "DownloadsOnConfigReload"));
ConfigSetConfigHandle(File_Downloads, arrayDownloads);
} }
/** /**
@ -103,8 +99,5 @@ DownloadsLoad()
public DownloadsOnConfigReload(ConfigFile:config) public DownloadsOnConfigReload(ConfigFile:config)
{ {
// Reload download config. // Reload download config.
if (config == ConfigDownloads) DownloadsLoad();
{
DownloadsLoad();
}
} }

View File

@ -72,6 +72,7 @@ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadc
// Forward event to sub-modules. // Forward event to sub-modules.
OverlaysOnRoundStart(); OverlaysOnRoundStart();
WeaponsOnRoundStart(); WeaponsOnRoundStart();
RoundStartOnRoundStart();
RoundEndOnRoundStart(); RoundEndOnRoundStart();
InfectOnRoundStart(); InfectOnRoundStart();
SEffectsOnRoundStart(); SEffectsOnRoundStart();
@ -90,8 +91,6 @@ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadc
*/ */
public Action:EventRoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadcast) public Action:EventRoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadcast)
{ {
RemoveObjectives();
// Forward events to modules. // Forward events to modules.
RoundEndOnRoundFreezeEnd(); RoundEndOnRoundFreezeEnd();
InfectOnRoundFreezeEnd(); InfectOnRoundFreezeEnd();
@ -154,32 +153,9 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad
// Get all required event info. // Get all required event info.
new index = GetClientOfUserId(GetEventInt(event, "userid")); new index = GetClientOfUserId(GetEventInt(event, "userid"));
// Reset FOV and overlay.
ToolsSetClientDefaultFOV(index, 90);
ClientCommand(index, "r_screenoverlay \"\"");
// Check if client is on a team.
if (ZRIsClientOnTeam(index))
{
// Turn off nightvision.
ToolsClientNightVision(index, false, false);
// Take nightvision away.
ToolsClientNightVision(index, false);
if (g_bZombieSpawned)
{
if (ZRIsClientOnTeam(index, CS_TEAM_T))
{
CS_SwitchTeam(index, CS_TEAM_CT);
CS_RespawnPlayer(index);
}
}
}
// Forward event to modules. // Forward event to modules.
InfectOnClientSpawn(index); InfectOnClientSpawn(index); // Some modules depend on this to finish first.
ClassOnClientSpawn(index); // Module event depends on infect module. ClassOnClientSpawn(index);
RestrictOnClientSpawn(index); RestrictOnClientSpawn(index);
SEffectsOnClientSpawn(index); SEffectsOnClientSpawn(index);
AccountOnClientSpawn(index); AccountOnClientSpawn(index);
@ -266,29 +242,15 @@ public Action:EventPlayerDeath(Handle:event, const String:name[], bool:dontBroad
// Get all required event info. // Get all required event info.
new index = GetClientOfUserId(GetEventInt(event, "userid")); new index = GetClientOfUserId(GetEventInt(event, "userid"));
new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
// Extinguish any flames to stop burning sounds.
ExtinguishEntity(index);
// If the attacker is valid, then continue.
if (ZRIsClientValid(attacker))
{
// If the client is a zombie, then continue.
if (InfectIsClientInfected(index))
{
// Add kill bonus to attacker's score.
new bonus = ClassGetKillBonus(attacker);
new score = ToolsClientScore(index, true, false);
ToolsClientScore(index, true, true, score + bonus);
}
}
// Forward event to modules. // Forward event to modules.
ClassOnClientDeath(index); ClassOnClientDeath(index);
RoundEndOnClientDeath(); RoundEndOnClientDeath();
InfectOnClientDeath(index, attacker);
SEffectsOnClientDeath(index); SEffectsOnClientDeath(index);
SpawnProtectOnClientDeath(index); SpawnProtectOnClientDeath(index);
RespawnOnClientDeath(index, attacker, weapon); RespawnOnClientDeath(index, attacker, weapon);
NapalmOnClientDeath(index);
ZSpawnOnClientDeath(index); ZSpawnOnClientDeath(index);
ZTeleOnClientDeath(index); ZTeleOnClientDeath(index);
ZHPOnClientDeath(index); ZHPOnClientDeath(index);

View File

@ -11,10 +11,9 @@
*/ */
/** /**
* Keyvalue handle to store hitgroups data. * Maximum length for a hitgroup name
*
* @redir config.inc
*/ */
#define HITGROUPS_MAX_LENGTH 32
/** /**
* @section Player hitgroup values. * @section Player hitgroup values.
@ -33,33 +32,28 @@
*/ */
/** /**
* Clears hitgroup data. * Hitgroup config data indexes.
*/ */
HitgroupsClearData() enum HitgroupsData
{ {
// Load hitgroup data. HITGROUPS_DATA_NAME = 0,
if (kvHitgroups != INVALID_HANDLE) HITGROUPS_DATA_INDEX,
{ HITGROUPS_DATA_DAMAGE,
CloseHandle(kvHitgroups); HITGROUPS_DATA_KNOCKBACK,
}
kvHitgroups = CreateKeyValues("hitgroups");
} }
/**
* Array handle to store hitgroups data.
*/
new Handle:arrayHitgroups = INVALID_HANDLE;
/** /**
* Loads hitgroup data from file. * Loads hitgroup data from file.
*/ */
HitgroupsLoad() HitgroupsLoad()
{ {
// Clear hitgroup data // Register config file.
HitgroupsClearData(); ConfigRegisterConfig(File_Hitgroups, Structure_Keyvalue, CONFIG_FILE_ALIAS_HITGROUPS);
// Get hitgroups config path.
decl String:pathhitgroups[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_HITGROUPS, pathhitgroups);
// Register config info.
ConfigRegisterConfig(ConfigHitgroups, false, GetFunctionByName(GetMyHandle(), "HitgroupsOnConfigReload"), _, pathhitgroups, CONFIG_FILE_ALIAS_HITGROUPS);
// If module is disabled, then stop. // If module is disabled, then stop.
new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]); new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
@ -68,23 +62,101 @@ HitgroupsLoad()
return; return;
} }
// Get hitgroups config path.
decl String:pathhitgroups[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_HITGROUPS, pathhitgroups);
// If file doesn't exist, then log and stop. // If file doesn't exist, then log and stop.
if (!exists) if (!exists)
{ {
// Log failure. // Log failure.
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Hitgroups", "Config Validation", "Missing hitgroups config file: %s", pathhitgroups); LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Hitgroups", "Config Validation", "Missing hitgroups config file: %s", pathhitgroups);
return; return;
} }
// Put file data into memory. // Set the path to the config file.
FileToKeyValues(kvHitgroups, pathhitgroups); ConfigSetConfigPath(File_Hitgroups, pathhitgroups);
// Load config from file and create array structure.
new bool:success = ConfigLoadConfig(File_Hitgroups, arrayHitgroups);
// Unexpected error, stop plugin.
if (!success)
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Hitgroups", "Config Validation", "Unexpected error encountered loading: %s", pathhitgroups);
return;
}
// Validate hitgroups config. // Validate hitgroups config.
HitgroupsValidateConfig(); new size = GetArraySize(arrayHitgroups);
if (!size)
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Hitgroups", "Config Validation", "No usable data found in hitgroups config file: %s", pathhitgroups);
}
// Now copy data to array structure.
HitgroupsCacheData();
// Set config data. // Set config data.
ConfigSetConfigLoaded(ConfigHitgroups, true); ConfigSetConfigLoaded(File_Hitgroups, true);
ConfigSetConfigHandle(ConfigHitgroups, kvHitgroups); ConfigSetConfigReloadFunc(File_Hitgroups, GetFunctionByName(GetMyHandle(), "HitgroupsOnConfigReload"));
ConfigSetConfigHandle(File_Hitgroups, arrayHitgroups);
}
/**
* Caches hitgroup data from file into arrays.
* Make sure the file is loaded before (ConfigLoadConfig) to prep array structure.
*/
HitgroupsCacheData()
{
// Get config's file path.
decl String:pathhitgroups[PLATFORM_MAX_PATH];
ConfigGetConfigPath(File_Hitgroups, pathhitgroups, sizeof(pathhitgroups));
new Handle:kvHitgroups;
new bool:success = ConfigOpenConfigFile(File_Hitgroups, kvHitgroups);
if (!success)
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Hitgroups", "Config Validation", "Unexpected error caching data from hitgroups config file: %s", pathhitgroups);
}
decl String:hitgroupname[HITGROUPS_MAX_LENGTH];
// x = array index
new size = GetArraySize(arrayHitgroups);
for (new x = 0; x < size; x++)
{
HitgroupsGetName(x, hitgroupname, sizeof(hitgroupname));
KvRewind(kvHitgroups);
if (!KvJumpToKey(kvHitgroups, hitgroupname))
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Hitgroups", "Config Validation", "Couldn't cache hitgroup data for: %s (check hitgroup config)", hitgroupname);
continue;
}
// General
new index = KvGetNum(kvHitgroups, "index", -1);
// Damage
new bool:damage = ConfigKvGetStringBool(kvHitgroups, "damage", "yes");
// Knockback (module)
new Float:knockback = KvGetFloat(kvHitgroups, "knockback", 1.0);
new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, x);
// Push data into array.
PushArrayCell(arrayHitgroup, index); // Index: 1
PushArrayCell(arrayHitgroup, damage); // Index: 2
PushArrayCell(arrayHitgroup, knockback); // Index: 3
}
// We're done with this file now, so we can close it.
CloseHandle(kvHitgroups);
} }
/** /**
@ -95,85 +167,91 @@ HitgroupsLoad()
public HitgroupsOnConfigReload(ConfigFile:config) public HitgroupsOnConfigReload(ConfigFile:config)
{ {
// Reload hitgroups config. // Reload hitgroups config.
if (config == ConfigHitgroups) HitgroupsLoad();
{
HitgroupsLoad();
}
} }
/** /**
* Validate hitgroup config file and settings. * Find the array index at which the hitgroup index is at.
*/
HitgroupsValidateConfig()
{
KvRewind(kvHitgroups);
if (!KvGotoFirstSubKey(kvHitgroups))
{
// Log that no data was loaded from hitgroup file.
LogPrintToLog(LOG_FORMAT_TYPE_NORMAL, "Hitgroups", "Config Validation", "No hitgroups listed in hitgroups.txt, disabling hitgroup-based modules.");
}
}
/**
* Retrieve hitgroup knockback value.
* *
* @param hitgroup The hitgroup index. * @param hitgroup The hitgroup index to search for.
* @return The knockback multiplier of the hitgroup. * @return The array index that contains the given hitgroup index.
*/ */
Float:HitgroupsGetHitgroupKnockback(hitgroup) stock HitgroupToIndex(hitgroup)
{ {
// Reset keyvalue's traversal stack. // x = Array index.
KvRewind(kvHitgroups); new size = GetArraySize(arrayHitgroups);
if (KvGotoFirstSubKey(kvHitgroups)) for (new x = 0; x < size; x++)
{ {
decl String:sHitgroup[4]; // Get hitgroup index at this array index.
new index = HitgroupsGetIndex(x);
do // If hitgroup indexes match, then return array index.
if (hitgroup == index)
{ {
KvGetSectionName(kvHitgroups, sHitgroup, sizeof(sHitgroup)); return x;
}
// If this is the right hitgroup, then return knockback for it.
if (hitgroup == StringToInt(sHitgroup))
{
return KvGetFloat(kvHitgroups, "knockback", 1.0);
}
} while (KvGotoNextKey(kvHitgroups));
} }
return 1.0; // Hitgroup index doesn't exist.
return -1;
}
/**
* Gets the name of a hitgroup at a given index.
* @param index The hitgroup index.
* @param hitgroup The string to return name in.
* @param maxlen The max length of the string.
*/
stock HitgroupsGetName(index, String:hitgroup[], maxlen)
{
// Get array handle of hitgroup at given index.
new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, index);
// Get hitgroup name.
GetArrayString(arrayHitgroup, _:HITGROUPS_DATA_NAME, hitgroup, maxlen);
}
/**
* Retrieve hitgroup index.
*
* @param index The array index.
* @return The hitgroup index.
*/
stock HitgroupsGetIndex(index)
{
// Get array handle of hitgroup at given index.
new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, index);
// Return hitgroup index of the hitgroup.
return GetArrayCell(arrayHitgroup, _:HITGROUPS_DATA_INDEX);
} }
/** /**
* Retrieve hitgroup damage value. * Retrieve hitgroup damage value.
* *
* @param hitgroup The hitgroup index. * @param index The array index.
* @return True if hitgroup can be damaged, false if not. * @return True if hitgroup can be damaged, false if not.
*/ */
bool:HitgroupsCanDamageHitgroup(hitgroup) stock bool:HitgroupsCanDamage(index)
{ {
// Reset keyvalue's traversal stack. // Get array handle of hitgroup at given index.
KvRewind(kvHitgroups); new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, index);
if (KvGotoFirstSubKey(kvHitgroups))
{
decl String:sHitgroup[4];
decl String:damage[8];
do
{
KvGetSectionName(kvHitgroups, sHitgroup, sizeof(sHitgroup));
// If this is the right hitgroup, then return knockback for it.
if (hitgroup == StringToInt(sHitgroup))
{
// Get config setting string.
KvGetString(kvHitgroups, "damage", damage, sizeof(damage), "yes");
// Return hitgroup's damage setting.
return ConfigSettingToBool(damage);
}
} while (KvGotoNextKey(kvHitgroups));
}
// If hitgroup is missing, then default to "yes." // Return true if hitgroup can be damaged, false if not.
return true; return bool:GetArrayCell(arrayHitgroup, _:HITGROUPS_DATA_DAMAGE);
}
/**
* Retrieve hitgroup knockback value.
*
* @param index The array index.
* @return The knockback multiplier of the hitgroup.
*/
stock Float:HitgroupsGetKnockback(index)
{
// Get array handle of hitgroup at given index.
new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, index);
// Return the knockback multiplier for the hitgroup.
return Float:GetArrayCell(arrayHitgroup, _:HITGROUPS_DATA_KNOCKBACK);
} }

View File

@ -213,6 +213,48 @@ InfectOnClientSpawn(client)
{ {
// Disable zombie flag on client. // Disable zombie flag on client.
bZombie[client] = false; bZombie[client] = false;
// Check if client is spawning on the terrorist team.
if (ZRIsClientOnTeam(client, CS_TEAM_T))
{
if (g_bZombieSpawned)
{
CS_SwitchTeam(client, CS_TEAM_CT);
CS_RespawnPlayer(client);
}
}
}
/**
* Client has been killed.
*
* @param client The client index.
* @param attacker The attacker index.
*/
InfectOnClientDeath(client, attacker)
{
// If attacker isn't valid, then stop.
if (!ZRIsClientValid(attacker))
{
return;
}
// If attacker isn't a human, then stop.
if (!InfectIsClientHuman(attacker))
{
return;
}
// If client isn't a zombie, then stop.
if (!InfectIsClientInfected(client))
{
return;
}
// Add kill bonus to attacker's score.
new bonus = ClassGetKillBonus(client);
new score = ToolsClientScore(attacker, true, false);
ToolsClientScore(attacker, true, true, score + bonus);
} }
/** Client has been hurt. /** Client has been hurt.
@ -348,7 +390,7 @@ public Action:InfectMotherZombie(Handle:timer)
new client; new client;
// Prune list of immune clients. // Prune list of immune clients.
// x = array index. // x = Array index.
// client = client index. // client = client index.
for (new x = 0; x < eligibleclients; x++) for (new x = 0; x < eligibleclients; x++)
{ {
@ -480,7 +522,7 @@ InfectClient(client, attacker = -1, bool:motherinfect = false)
bZombie[client] = true; bZombie[client] = true;
// Get a list of all client's weapon indexes. // Get a list of all client's weapon indexes.
new weapons[WeaponsType]; new weapons[WeaponsSlot];
WeaponsGetClientWeapons(client, weapons); WeaponsGetClientWeapons(client, weapons);
// Check if weapons drop is enabled. // Check if weapons drop is enabled.
@ -499,7 +541,7 @@ InfectClient(client, attacker = -1, bool:motherinfect = false)
if (weaponsdrop) if (weaponsdrop)
{ {
// If this is the knife slot, then stop. // If this is the knife slot, then stop.
if (WeaponsType:x == Type_Melee) if (WeaponsSlot:x == Slot_Melee)
{ {
continue; continue;
} }
@ -515,7 +557,7 @@ InfectClient(client, attacker = -1, bool:motherinfect = false)
} }
// If client has no knife, give them one. // If client has no knife, give them one.
if (GetPlayerWeaponSlot(client, _:Type_Melee) == -1) if (GetPlayerWeaponSlot(client, _:Slot_Melee) == -1)
{ {
GivePlayerItem(client, "weapon_knife"); GivePlayerItem(client, "weapon_knife");
} }

View File

@ -70,14 +70,22 @@ KnockbackOnClientHurt(client, attacker, const String:weapon[], hitgroup, dmg_hea
TR_GetEndPosition(clientloc); TR_GetEndPosition(clientloc);
} }
// Retrieve weapon knockback boost. new weaponindex = WeaponsNameToIndex(weapon);
new Float:boostWeapon = WeaponGetWeaponKnockback(weapon); if (weaponindex != -1)
{
// Apply weapon knockback multiplier.
knockback *= WeaponsGetKnockback(weaponindex);
}
// Retrieve hitgroup knockback boost. new hitgroupindex = HitgroupToIndex(hitgroup);
new Float:boostHitgroup = HitgroupsGetHitgroupKnockback(hitgroup); if (hitgroupindex != -1)
{
// Apply hitgroup knockback multiplier.
knockback *= HitgroupsGetKnockback(hitgroupindex);
}
// Apply all knockback multipliers. // Apply damage knockback multiplier.
knockback *= float(dmg_health) * boostWeapon * boostHitgroup; knockback *= float(dmg_health);
// Apply knockback. // Apply knockback.
KnockbackSetVelocity(client, attackerloc, clientloc, knockback); KnockbackSetVelocity(client, attackerloc, clientloc, knockback);

View File

@ -52,7 +52,7 @@ MenuMain(client)
AddMenuItem(menu_main, "zspawn", zspawn); AddMenuItem(menu_main, "zspawn", zspawn);
AddMenuItem(menu_main, "ztele", ztele); AddMenuItem(menu_main, "ztele", ztele);
AddMenuItem(menu_main, "zhp", zhp); AddMenuItem(menu_main, "zhp", zhp);
AddMenuItem(menu_main, "zmarket", zmarket, MenuGetItemDraw(g_bMarket)); AddMenuItem(menu_main, "zmarket", zmarket);
// Display menu to client. // Display menu to client.
DisplayMenu(menu_main, client, MENU_TIME_FOREVER); DisplayMenu(menu_main, client, MENU_TIME_FOREVER);
@ -113,8 +113,6 @@ public MenuMainHandle(Handle:menu, MenuAction:action, client, slot)
// Select zmarket. // Select zmarket.
case 5: case 5:
{ {
// Copy return to resend variable.
resend = !ZMarketMenu(client);
} }
} }

View File

@ -22,22 +22,21 @@
/** /**
* Array that stores a list of validated models. * Array that stores a list of validated models.
*
* @redir config.inc
*/ */
new Handle:arrayModels = INVALID_HANDLE;
/** /**
* Prepare all model/download data. * Prepare all model/download data.
*/ */
ModelsLoad() ModelsLoad()
{ {
// Register config file.
ConfigRegisterConfig(File_Models, Structure_List, CONFIG_FILE_ALIAS_MODELS);
// Get models file path. // Get models file path.
decl String:pathmodels[PLATFORM_MAX_PATH]; decl String:pathmodels[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_MODELS, pathmodels); new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_MODELS, pathmodels);
// Register config info.
ConfigRegisterConfig(ConfigModels, false, GetFunctionByName(GetMyHandle(), "ModelsOnConfigReload"), _, pathmodels, CONFIG_FILE_ALIAS_MODELS);
// If file doesn't exist, then log and stop. // If file doesn't exist, then log and stop.
if (!exists) if (!exists)
{ {
@ -45,18 +44,16 @@ ModelsLoad()
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Models", "Config Validation", "Fatal Error: Missing models file: \"%s\"", pathmodels); LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Models", "Config Validation", "Fatal Error: Missing models file: \"%s\"", pathmodels);
} }
// If model array exists, then destroy it. // Set the path to the config file.
if (arrayModelsList != INVALID_HANDLE) ConfigSetConfigPath(File_Models, pathmodels);
{
CloseHandle(arrayModelsList);
}
arrayModelsList = ConfigLinesToArray(pathmodels); // Load config from file and create array structure.
new bool:success = ConfigLoadConfig(File_Models, arrayModels);
// If array couldn't be created, then fail. // Unexpected error, stop plugin.
if (arrayModelsList == INVALID_HANDLE) if (!success)
{ {
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Models", "Config Validation", "Fatal Error: Error parsing \"%s\"", pathmodels); LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Models", "Config Validation", "Fatal Error: Unexpected error encountered loading: %s", pathmodels);
} }
new modelcount; new modelcount;
@ -74,13 +71,13 @@ ModelsLoad()
new FileType:type; new FileType:type;
new models = modelcount = GetArraySize(arrayModelsList); new models = modelcount = GetArraySize(arrayModels);
// x = model array index. // x = model array index.
for (new x = 0; x < models; x++) for (new x = 0; x < models; x++)
{ {
// Get base model path (rawline in models.txt) // Get base model path (rawline in models.txt)
GetArrayString(arrayModelsList, x, modelbase, sizeof(modelbase)); GetArrayString(arrayModels, x, modelbase, sizeof(modelbase));
// Explode path into pieces. (separated by "/") // Explode path into pieces. (separated by "/")
new strings = ExplodeString(modelbase, "/", baseexploded, MODELS_PATH_MAX_DEPTH, MODELS_PATH_DIR_MAX_LENGTH); new strings = ExplodeString(modelbase, "/", baseexploded, MODELS_PATH_MAX_DEPTH, MODELS_PATH_DIR_MAX_LENGTH);
@ -137,7 +134,7 @@ ModelsLoad()
else else
{ {
// Remove client from array. // Remove client from array.
RemoveFromArray(arrayModelsList, x); RemoveFromArray(arrayModels, x);
// Subtract one from count. // Subtract one from count.
models--; models--;
@ -160,20 +157,16 @@ ModelsLoad()
} }
// Set config data. // Set config data.
ConfigSetConfigLoaded(ConfigModels, true); ConfigSetConfigLoaded(File_Models, true);
ConfigSetConfigHandle(ConfigModels, arrayModelsList); ConfigSetConfigReloadFunc(File_Models, GetFunctionByName(GetMyHandle(), "ModelsOnConfigReload"));
ConfigSetConfigHandle(File_Models, arrayModels);
} }
/** /**
* Called when configs are being reloaded. * Called when config is being reloaded.
*
* @param config The config being reloaded. (only if 'all' is false)
*/ */
public ModelsOnConfigReload(ConfigFile:config) public ModelsOnConfigReload(ConfigFile:config)
{ {
// Reload model config. // Reload models config.
if (config == ConfigModels) ModelsLoad();
{
ModelsLoad();
}
} }

View File

@ -47,6 +47,17 @@ NapalmOnClientHurt(client, const String:weapon[])
} }
} }
/**
* Client has been killed.
*
* @param client The client index.
*/
NapalmOnClientDeath(client)
{
// Extinguish any flames to stop burning sounds.
ExtinguishEntity(client);
}
/** /**
* Weapon has been fired. * Weapon has been fired.
* *

View File

@ -164,6 +164,7 @@ OverlaysClientUpdateOverlay(client, OverlaysChannel:channel = OVERLAYS_CHANNEL_N
{ {
channel = OverlaysClientFindChannel(client); channel = OverlaysClientFindChannel(client);
} }
// Stop here if client has no overlay channel enabled. // Stop here if client has no overlay channel enabled.
if (channel == OVERLAYS_CHANNEL_NONE) if (channel == OVERLAYS_CHANNEL_NONE)
{ {
@ -172,6 +173,12 @@ OverlaysClientUpdateOverlay(client, OverlaysChannel:channel = OVERLAYS_CHANNEL_N
return; return;
} }
// If channel we are updating is disabled, then stop.
if (!g_bOverlayChannel[client][channel])
{
return;
}
// If dxLevel is 0, then query on client failed, so try again, then stop. // If dxLevel is 0, then query on client failed, so try again, then stop.
if (!g_iOverlaysDXL[client]) if (!g_iOverlaysDXL[client])
{ {

View File

@ -71,8 +71,8 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
if (strcmp(modelpath, "random", false) == 0) if (strcmp(modelpath, "random", false) == 0)
{ {
// TODO: Make a function that gets a random model from the specified team. // TODO: Make a function that gets a random model from the specified team.
new randmodel = GetRandomInt(0, GetArraySize(arrayModelsList) - 1); new randmodel = GetRandomInt(0, GetArraySize(arrayModels) - 1);
GetArrayString(arrayModelsList, randmodel, modelpath, sizeof(modelpath)); GetArrayString(arrayModels, randmodel, modelpath, sizeof(modelpath));
Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath); Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath);
} }

View File

@ -9,10 +9,30 @@
* ============================================================================ * ============================================================================
*/ */
ClassOnCommandsCreate()
{
// Create base class commands.
RegConsoleCmd("zr_class_dump", ClassDumpCommand, "Dumps class data at a specified index in the specified cache. Usage: zr_class_dump <cachetype> <index|targetname>");
RegAdminCmd("zr_class_modify", ClassModifyCommand, ADMFLAG_GENERIC, "Modify class data on one or more classes. Usage: zr_class_modify <classname|\"zombies\"|\"humans\"|\"admins\"> <attribute> <value> [is_multiplier]");
}
/** /**
* Dumps class data at a specified index in the specified cache. * Hook commands related to classes here.
*/ */
public Action:Command_ClassDump(client, argc) ClassOnCommandsHook()
{
// Forward event to sub-modules.
ClassOverlayOnCommandsHook();
}
/**
* Command callback. (zr_class_dump)
* Dumps class data at a specified index in the specified cache.
*
* @param client The client index.
* @param argc Argument count.
*/
public Action:ClassDumpCommand(client, argc)
{ {
decl String:syntax[1024]; decl String:syntax[1024];
syntax[0] = 0; syntax[0] = 0;
@ -124,7 +144,7 @@ public Action:Command_ClassDump(client, argc)
* Note: Original values are retrieved from the original class cache, not the * Note: Original values are retrieved from the original class cache, not the
* modified class cache. * modified class cache.
*/ */
public Action:Command_ClassModify(client, argc) public Action:ClassModifyCommand(client, argc)
{ {
decl String:syntax[1024]; decl String:syntax[1024];
syntax[0] = 0; syntax[0] = 0;
@ -335,7 +355,7 @@ public Action:Command_ClassModify(client, argc)
* @param value New value to set. * @param value New value to set.
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
bool:ClassModifyBoolean(classindex, attributeflag, bool:value) stock bool:ClassModifyBoolean(classindex, attributeflag, bool:value)
{ {
// Validate class index. // Validate class index.
if (!ClassValidateIndex(classindex)) if (!ClassValidateIndex(classindex))
@ -378,7 +398,7 @@ bool:ClassModifyBoolean(classindex, attributeflag, bool:value)
* disable. Value is ignored if this is non-zero. * disable. Value is ignored if this is non-zero.
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0.0) stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0.0)
{ {
// Validate class index. // Validate class index.
if (!ClassValidateIndex(classindex)) if (!ClassValidateIndex(classindex))
@ -481,7 +501,7 @@ ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0.0)
* Not all attributes support multipliers. * Not all attributes support multipliers.
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier = false) stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier = false)
{ {
// Validate class index. // Validate class index.
if (!ClassValidateIndex(classindex)) if (!ClassValidateIndex(classindex))
@ -568,7 +588,7 @@ ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier = fal
* @param value New value to set. * @param value New value to set.
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
ClassModifyString(classindex, attributeflag, const String:value[]) stock ClassModifyString(classindex, attributeflag, const String:value[])
{ {
// Validate class index. // Validate class index.
if (!ClassValidateIndex(classindex)) if (!ClassValidateIndex(classindex))

View File

@ -34,15 +34,6 @@ ClassClientInit(client)
ClassOverlayClientInit(client); ClassOverlayClientInit(client);
} }
/**
* Hook commands related to classes here.
*/
ClassOnCommandsHook()
{
// Forward event to sub-modules.
ClassOverlayOnCommandsHook();
}
/** /**
* Called when all modules are done loading. * Called when all modules are done loading.
*/ */
@ -108,7 +99,6 @@ ClassOnClientSpawn(client)
// Check if the player should spawn in admin mode. // Check if the player should spawn in admin mode.
if (ClassPlayerAdminMode[client]) if (ClassPlayerAdminMode[client])
{ {
// Mark player as in admin mode. // Mark player as in admin mode.
ClassPlayerInAdminMode[client] = true; ClassPlayerInAdminMode[client] = true;
@ -137,11 +127,11 @@ ClassOnClientDeath(client)
// Disable class attributes with timers. // Disable class attributes with timers.
ClassHealthRegenStop(client); ClassHealthRegenStop(client);
// Disable overlay.
OverlaysClientSetChannelState(client, OVERLAYS_CHANNEL_CLASSES, true, false, false, true);
// Set client's FOV back to normal. // Set client's FOV back to normal.
ToolsSetClientDefaultFOV(client, 90); ToolsSetClientDefaultFOV(client, 90);
// Forward event to sub-modules.
ClassOverlayOnClientDeath(client);
} }
ClassOnClientInfected(client, bool:motherzombie = false) ClassOnClientInfected(client, bool:motherzombie = false)

View File

@ -209,14 +209,6 @@ ClassMenuSelect(client, teamid)
AddMenuItem(menu, classname, menuitem); AddMenuItem(menu, classname, menuitem);
} }
} }
else
{
// No classes found. Display message. The main class menu should
// prevent this from happening, but we print a message just in case.
// THIS TRANSLATION PHRASES IS NOT IN FILE.
Format(menuitem, sizeof(menuitem), "%t\n", "Classes menu not found");
AddMenuItem(menu, classname, menuitem, ITEMDRAW_RAWLINE);
}
SetMenuExitBackButton(menu, true); SetMenuExitBackButton(menu, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER); DisplayMenu(menu, client, MENU_TIME_FOREVER);

View File

@ -54,7 +54,7 @@ ClassOverlayOnCommandsHook()
// Explode string into array indexes. // Explode string into array indexes.
new cmdcount = ExplodeString(togglecmds, ", ", arrayCmds, CLASSOVERLAY_TOGGLE_MAX_CMDS, CLASSOVERLAY_TOGGLE_MAX_LENGTH); new cmdcount = ExplodeString(togglecmds, ", ", arrayCmds, CLASSOVERLAY_TOGGLE_MAX_CMDS, CLASSOVERLAY_TOGGLE_MAX_LENGTH);
// x = array index. // x = Array index.
// arrayCmds[x] = suicide command. // arrayCmds[x] = suicide command.
for (new x = 0; x <= cmdcount - 1; x++) for (new x = 0; x <= cmdcount - 1; x++)
{ {
@ -83,6 +83,20 @@ ClassOverlayOnClientSpawn(client)
TranslationPrintHUDText(client, "Classes overlay toggle", togglecmds); TranslationPrintHUDText(client, "Classes overlay toggle", togglecmds);
} }
// Update class overlay.
OverlaysClientUpdateOverlay(client, OVERLAYS_CHANNEL_CLASSES);
}
/**
* Client has been killed.
*
* @param client The client index.
*/
ClassOverlayOnClientDeath(client)
{
// Disable overlay.
OverlaysClientSetChannelState(client, OVERLAYS_CHANNEL_CLASSES, true, false, false, true);
} }
/** /**
@ -127,7 +141,7 @@ ClassOverlayInitialize(client, const String:overlay[])
} }
/** /**
* Command callback (See zr_classes_overlay_togglecmds) * Command callback. (See zr_classes_overlay_togglecmds)
* Toggles nightvision of a client. * Toggles nightvision of a client.
* *
* @param client The client index. * @param client The client index.

View File

@ -252,9 +252,8 @@ enum ClassDataTypes
/** /**
* Keyvalue handle to store class data. * Keyvalue handle to store class data.
*
* @redir config.inc
*/ */
new Handle:kvClassData = INVALID_HANDLE;
/** /**
* The original class data. This array only changed when class data is loaded. * The original class data. This array only changed when class data is loaded.
@ -322,20 +321,20 @@ new ClassPlayerNextAdminClass[MAXPLAYERS + 1];
*/ */
ClassLoad() ClassLoad()
{ {
// Register config file.
ConfigRegisterConfig(File_Classes, Structure_Keyvalue, CONFIG_FILE_ALIAS_CLASSES);
// Make sure kvClassData is ready to use. // Make sure kvClassData is ready to use.
if (kvClassData != INVALID_HANDLE) if (kvClassData != INVALID_HANDLE)
{ {
CloseHandle(kvClassData); CloseHandle(kvClassData);
} }
kvClassData = CreateKeyValues("classes"); kvClassData = CreateKeyValues(CONFIG_FILE_ALIAS_CLASSES);
// Get weapons config path. // Get weapons config path.
decl String:pathclasses[PLATFORM_MAX_PATH]; decl String:pathclasses[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_CLASSES, pathclasses); new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_CLASSES, pathclasses);
// Register config info.
ConfigRegisterConfig(ConfigClasses, false, GetFunctionByName(GetMyHandle(), "ClassOnConfigReload"), _, pathclasses, CONFIG_FILE_ALIAS_CLASSES);
// If file doesn't exist, then log and stop. // If file doesn't exist, then log and stop.
if (!exists) if (!exists)
{ {
@ -463,8 +462,10 @@ ClassLoad()
LogPrintToLog(LOG_FORMAT_TYPE_NORMAL, "Classes", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", ClassCount, ClassCount - failedcount, failedcount); LogPrintToLog(LOG_FORMAT_TYPE_NORMAL, "Classes", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", ClassCount, ClassCount - failedcount, failedcount);
// Set config data. // Set config data.
ConfigSetConfigLoaded(ConfigClasses, true); ConfigSetConfigLoaded(File_Classes, true);
ConfigSetConfigHandle(ConfigClasses, kvClassData); ConfigSetConfigReloadFunc(File_Classes, GetFunctionByName(GetMyHandle(), "ClassOnConfigReload"));
// ConfigSetConfigHandle(File_Classes, INVALID_HANDLE);
ConfigSetConfigPath(File_Classes, pathclasses);
} }
/** /**
@ -475,9 +476,6 @@ ClassLoad()
public ClassOnConfigReload(ConfigFile:config) public ClassOnConfigReload(ConfigFile:config)
{ {
// Reload class config. // Reload class config.
if (config == ConfigClasses)
{
}
} }
/** /**

View File

@ -306,7 +306,7 @@ RoundEndBalanceTeams()
// Move all clients to T // Move all clients to T
// x = array index. // x = Array index.
// client = client index. // client = client index.
for (new x = 0; x < eligibleclients; x++) for (new x = 0; x < eligibleclients; x++)
{ {

58
src/zr/roundstart.inc Normal file
View File

@ -0,0 +1,58 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: roundstart.inc
* Type: Core
* Description: Handles round start actions.
*
* ============================================================================
*/
/**
* List of objective entities.
*/
#define ROUNDSTART_OBJECTIVE_ENTITIES "func_bomb_target|func_hostage_rescue|c4|hostage_entity"
/**
* The round is starting.
*/
RoundStartOnRoundStart()
{
// Kill all objective entities.
RoundStartKillObjectives();
}
/**
* Kills all objective entities.
*/
RoundStartKillObjectives()
{
decl String:classname[64];
// Get max entity count.
new maxentities = GetMaxEntities();
// x = entity index.
for (new x = 0; x <= maxentities; x++)
{
// If entity isn't valid, then stop.
if(!IsValidEdict(x))
{
continue;
}
// Get valid edict's classname.
GetEdictClassname(x, classname, sizeof(classname));
// Check if it matches any objective entities, then stop if it doesn't.
if(StrContains(ROUNDSTART_OBJECTIVE_ENTITIES, classname) == -1)
{
continue;
}
// Entity is an objective, kill it.
RemoveEdict(x);
}
}

View File

@ -121,8 +121,6 @@ public Action:SayHooksCmdSay(client, argc)
// Client triggered ZMarket flag. // Client triggered ZMarket flag.
case SAYHOOKS_KEYWORD_FLAG_ZMARKET: case SAYHOOKS_KEYWORD_FLAG_ZMARKET:
{ {
// Send market menu.
success = ZMarketMenu(client);
} }
} }

View File

@ -18,11 +18,8 @@ new g_iToolsBaseVelocity;
new g_iToolsLMV; new g_iToolsLMV;
new g_iToolsHasNightVision; new g_iToolsHasNightVision;
new g_iToolsNightVisionOn; new g_iToolsNightVisionOn;
new g_iToolsCollisionGroup;
new g_iToolsAccount;
new g_iToolsDefaultFOV; new g_iToolsDefaultFOV;
new g_iToolsInBuyZone;
new g_iToolsActiveWeapon;
/** /**
* @endsection * @endsection
*/ */
@ -93,20 +90,6 @@ ToolsFindOffsets()
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CCSPlayer::m_bNightVisionOn\" was not found."); LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CCSPlayer::m_bNightVisionOn\" was not found.");
} }
// If offset "m_CollisionGroup" can't be found, then stop the plugin.
g_iToolsCollisionGroup = FindSendPropInfo("CBaseEntity", "m_CollisionGroup");
if (g_iToolsCollisionGroup == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBaseEntity::m_CollisionGroup\" was not found.");
}
// If offset "m_iAccount" can't be found, then stop the plugin.
g_iToolsAccount = FindSendPropInfo("CCSPlayer", "m_iAccount");
if (g_iToolsAccount == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CCSPlayer::m_iAccount\" was not found.");
}
// If offset "m_iDefaultFOV" can't be found, then stop the plugin. // If offset "m_iDefaultFOV" can't be found, then stop the plugin.
g_iToolsDefaultFOV = FindSendPropInfo("CBasePlayer", "m_iDefaultFOV"); g_iToolsDefaultFOV = FindSendPropInfo("CBasePlayer", "m_iDefaultFOV");
if (g_iToolsDefaultFOV == -1) if (g_iToolsDefaultFOV == -1)
@ -114,19 +97,11 @@ ToolsFindOffsets()
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBasePlayer::m_iDefaultFOV\" was not found."); LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBasePlayer::m_iDefaultFOV\" was not found.");
} }
// If offset "m_bInBuyZone" can't be found, then stop the plugin. // Forward event to modules.
g_iToolsInBuyZone = FindSendPropInfo("CCSPlayer", "m_bInBuyZone"); WeaponsOnOffsetsFound();
if (g_iToolsInBuyZone == -1) AccountOnOffsetsFound();
{ AntiStickOnOffsetsFound();
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CCSPlayer::m_bInBuyZone\" was not found."); ZMarketOnOffsetsFound();
}
// 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.");
}
} }
/** /**

View File

@ -153,8 +153,8 @@ stock TranslationPrintToChatAll(bool:server, bool:admin, any:...)
continue; continue;
} }
// Set translation target // Set translation target to client.
SetGlobalTransTarget(LANG_SERVER); SetGlobalTransTarget(x);
// Translate phrase. // Translate phrase.
VFormat(translation, sizeof(translation), "%t", 3); VFormat(translation, sizeof(translation), "%t", 3);
@ -327,9 +327,20 @@ stock TranslationReplyToCommand(client, any:...)
decl String:translation[TRANSLATION_MAX_LENGTH_CHAT]; decl String:translation[TRANSLATION_MAX_LENGTH_CHAT];
VFormat(translation, sizeof(translation), "%t", 2); VFormat(translation, sizeof(translation), "%t", 2);
// Format string to create plugin style. if (ZRIsClientValid(client))
TranslationPluginFormatString(translation, sizeof(translation)); {
// Format string to create plugin style. (color)
// Print translated phrase to client. TranslationPluginFormatString(translation, sizeof(translation));
ReplyToCommand(client, translation);
// Print translated phrase to client's chat/console.
PrintToChat(client, translation);
}
else
{
// Format string to create plugin style. (no color)
TranslationPluginFormatString(translation, sizeof(translation), false);
// Print to server.
PrintToServer(translation);
}
} }

View File

@ -1,165 +0,0 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: markethandler.inc
* Type: Core
* Description: Handles market (optional plugin) API, natives, and forwards.
*
* ============================================================================
*/
/**
* Global variable set to true if market plugin is installed
*/
new bool:g_bMarket;
/**
* Set global market flag variable
*/
MarketInit()
{
// Set market variable to true if market is installed.
g_bMarket = LibraryExists("market");
}
/**
* Sends market menu to client.
*
* @param client The client index.
*/
bool:ZMarketMenu(client)
{
// If market is disabled, then stop.
if (!g_bMarket)
{
// Tell client market is disabled.
TranslationPrintToChat(client, "Feature is disabled");
return false;
}
// If player is dead, then stop.
if (!IsPlayerAlive(client))
{
// Tell player they must be alive.
TranslationPrintToChat(client, "Must be alive");
return false;
}
// Check buyzone cvar to see if client has to be in a buyzone to use.
new bool:buyzone = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]);
if (!ZMarketIsClientInBuyZone(client) && buyzone)
{
// Tell client they must be in a buyzone.
TranslationPrintCenterText(client, "Market out of buyzone");
return false;
}
// Set translate target to client.
SetGlobalTransTarget(client);
// Format title and rebuy lines.
decl String:title[64];
decl String:rebuy[64];
Format(title, sizeof(title), "%t\n ", "Market title");
Format(rebuy, sizeof(rebuy), "%t\n ", "Market rebuy");
// Send market menu.
Market_Send(client, title, rebuy);
// Successfully sent the market menu.
return true;
}
/**
* Checks if a client is in a buyzone.
*
* @param client The client index.
*/
bool:ZMarketIsClientInBuyZone(client)
{
// Return if client is in buyzone.
return bool:GetEntData(client, g_iToolsInBuyZone);
}
/**
* (Market) Forward called when a client selects a weapon from the market.
*
* @param client The client index.
* @param weaponid The unique weapon ID used for market natives.
* @return True to allow market to take over, false to block purchase.
*/
public bool:Market_OnWeaponSelected(client, String:weaponid[])
{
// If player is dead or weaponid is invalid, then stop.
if (!weaponid[0] || !IsPlayerAlive(client))
{
return false;
}
// If player is a zombie, then stop.
if (InfectIsClientInfected(client))
{
TranslationPrintToChat(client, "Zombie cant use weapon");
return false;
}
// If player is using the rebuy option then allow.
if (StrEqual(weaponid, "rebuy"))
{
return true;
}
decl String:display[64];
decl String:weapon[WEAPONS_MAX_LENGTH];
new price;
// If the market plugin can't find info about the weapon, then stop.
if (!Market_GetWeaponIDInfo(weaponid, display, weapon, price))
{
return false;
}
// Strip "weapon_" from entity name.
ReplaceString(weapon, sizeof(weapon), "weapon_", "");
// If the weapon is restricted, then stop.
if (RestrictIsWeaponRestricted(weapon))
{
TranslationPrintToChat(client, "Weapon is restricted", weapon);
return false;
}
// Check if buyzone cvar is enabled, and if the client is in a buyzone.
new bool:buyzone = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]);
if (!ZMarketIsClientInBuyZone(client) && buyzone)
{
TranslationPrintCenterText(client, "Market out of buyzone");
return false;
}
return true;
}
/**
* (Market) Forward called one frame after a client selects a weapon from the market.
*
* @param client The client index.
* @param allowed True when the weapon was purchased successfully, false otherwise.
*/
public Market_PostOnWeaponSelected(client, &bool:allowed)
{
// If the purchase wasn't allowed, then stop.
if (!allowed)
{
return;
}
// Resend market menu.
ZMarketMenu(client);
}

View File

@ -11,28 +11,14 @@
*/ */
/** /**
* Weapons Menus * Array to store the client's current weapon type within menu.
*/ */
enum WeaponsMenu new g_iCurWeaponType[MAXPLAYERS + 1];
{
Weapon,
WeaponGroup,
}
/**
* Array to store the client's current weapon menu.
*/
new WeaponsMenu:curMenuWeapons[MAXPLAYERS + 1];
/**
* Array to store the client's current weapon group menu.
*/
new String:curMenuGroup[WEAPONS_MAX_LENGTH][MAXPLAYERS + 1];
/** /**
* Sends main weapon menu to client. * Sends main weapon menu to client.
* @param client The client index. * @param client The client index.
*/ */
WeaponsMenuMain(client) WeaponsMenuMain(client)
{ {
// Create menu handle. // Create menu handle.
@ -42,17 +28,15 @@ WeaponsMenuMain(client)
SetMenuTitle(menu_weapons_main, "%t\n ", "Weapons menu main title"); SetMenuTitle(menu_weapons_main, "%t\n ", "Weapons menu main title");
decl String:toggleweaponrestriction[64]; decl String:restrict[64];
decl String:togglewgrouprestriction[64];
decl String:zmarket[64]; decl String:zmarket[64];
Format(toggleweaponrestriction, sizeof(toggleweaponrestriction), "%t", "Weapons menu main toggle weapon restrict"); Format(restrict, sizeof(restrict), "%t", "Weapons menu main restrict");
Format(togglewgrouprestriction, sizeof(togglewgrouprestriction), "%t", "Weapons menu main toggle weapon group restrict");
Format(zmarket, sizeof(zmarket), "%t", "Weapons menu main market"); Format(zmarket, sizeof(zmarket), "%t", "Weapons menu main market");
AddMenuItem(menu_weapons_main, "toggleweaponrestriction", toggleweaponrestriction); // Draw items, make unselectable if module is disabled.
AddMenuItem(menu_weapons_main, "togglewgrouprestriction", togglewgrouprestriction); AddMenuItem(menu_weapons_main, "restrict", restrict, MenuGetItemDraw(GetConVarBool(g_hCvarsList[CVAR_WEAPONS_RESTRICT])));
AddMenuItem(menu_weapons_main, "zmarket", zmarket, MenuGetItemDraw(g_bMarket)); AddMenuItem(menu_weapons_main, "zmarket", zmarket, MenuGetItemDraw(GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET])));
// Create a "Back" button to the weapons main menu. // Create a "Back" button to the weapons main menu.
SetMenuExitBackButton(menu_weapons_main, true); SetMenuExitBackButton(menu_weapons_main, true);
@ -75,17 +59,15 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client
{ {
switch(slot) switch(slot)
{ {
// Weapons.
case 0: case 0:
{ {
WeaponsMenuWeapons(client, Weapon); WeaponsMenuTypes(client);
} }
// ZMarket.
case 1: case 1:
{ {
WeaponsMenuWeapons(client, WeaponGroup); WeaponsMenuZMarket(client);
}
case 2:
{
WeaponsMenuMarket(client);
} }
} }
} }
@ -95,7 +77,7 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client
// Client hit "Back" button. // Client hit "Back" button.
if (slot == MenuCancel_ExitBack) if (slot == MenuCancel_ExitBack)
{ {
ZRAdminMenu(client); // Re-open admin menu.
} }
} }
// Client hit "Exit" button. // Client hit "Exit" button.
@ -106,159 +88,63 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client
} }
/** /**
* Sends weapon list menu to client. * Sends weapon type list to client.
* @param client The client index. * @param client The client index.
*/ */
WeaponsMenuWeapons(client, WeaponsMenu:type) WeaponsMenuTypes(client)
{ {
// Set the current action client is performing on a weapon. (see enum WeaponsMenu)
curMenuWeapons[client] = type;
// Create menu handle. // Create menu handle.
new Handle:menu_weapons_weapons = CreateMenu(WeaponsMenuWeaponsHandle); new Handle:menu_weapons_types = CreateMenu(WeaponsMenuTypesHandle);
SetGlobalTransTarget(client); SetGlobalTransTarget(client);
// If client wants to perform an action on a single weapon, show weapon list. SetMenuTitle(menu_weapons_types, "%t\n ", "Weapons menu types title");
switch(curMenuWeapons[client])
decl String:typename[WEAPONS_MAX_LENGTH];
// x = Array index.
new size = GetArraySize(arrayWeaponTypes);
for (new x = 0; x < size; x++)
{ {
case Weapon: // Get name of type.
{ RestrictWeaponTypeGetName(x, typename, sizeof(typename));
SetMenuTitle(menu_weapons_weapons, "%t\n ", "Weapons menu weapons weapon title");
// Add item to menu.
decl String:weapon[WEAPONS_MAX_LENGTH]; AddMenuItem(menu_weapons_types, typename, typename);
decl String:display[WEAPONS_MAX_LENGTH + 1];
new Handle:arrayWeapons = INVALID_HANDLE;
new size = WeaponsCreateWeaponArray(arrayWeapons);
// x = Array index.
for (new x = 0; x < size; x++)
{
GetArrayString(arrayWeapons, x, weapon, sizeof(weapon));
strcopy(display, sizeof(display), weapon);
if (RestrictIsWeaponRestricted(weapon))
{
Format(display, sizeof(display), "%s*", weapon);
}
// If weapon restriction is blocked for the menu, disable option.
new bool:menu = WeaponsIsWeaponMenu(weapon);
if (menu)
{
AddMenuItem(menu_weapons_weapons, weapon, display);
}
else
{
AddMenuItem(menu_weapons_weapons, weapon, display, ITEMDRAW_DISABLED);
}
}
// If there are no weapons, add an "(Empty)" line.
if (size == 0)
{
decl String:empty[64];
Format(empty, sizeof(empty), "%t", "Menu empty");
AddMenuItem(menu_weapons_weapons, "empty", empty, ITEMDRAW_DISABLED);
}
// Kill the array handle.
CloseHandle(arrayWeapons);
}
// If client wants to perform an action on a weapon group, show custom group list.
case WeaponGroup:
{
SetMenuTitle(menu_weapons_weapons, "%t\n ", "Weapons menu weapons group title");
decl String:weapongroup[WEAPONS_MAX_LENGTH];
decl String:display[WEAPONS_MAX_LENGTH + 2];
new Handle:arrayWeaponGroups = INVALID_HANDLE;
new size = RestrictCreateGroupArray(arrayWeaponGroups);
// x = Array index.
for (new x = 0; x < size; x++)
{
GetArrayString(arrayWeaponGroups, x, weapongroup, sizeof(weapongroup));
strcopy(display, sizeof(display), weapongroup);
if (RestrictIsPartialRestricted(weapongroup))
{
Format(display, sizeof(display), "%s*", weapongroup);
}
else if (RestrictIsGroupRestricted(weapongroup))
{
Format(display, sizeof(display), "%s**", weapongroup);
}
AddMenuItem(menu_weapons_weapons, weapongroup, display);
}
// If there are no weapons, add an "(Empty)" line.
if (size == 0)
{
decl String:empty[64];
Format(empty, sizeof(empty), "%t", "Menu empty");
AddMenuItem(menu_weapons_weapons, "empty", empty, ITEMDRAW_DISABLED);
}
// Kill the array handle
CloseHandle(arrayWeaponGroups);
}
} }
SetMenuExitBackButton(menu_weapons_weapons, true); // If there are no weapons, add an "(Empty)" line.
if (size == 0)
{
decl String:empty[64];
Format(empty, sizeof(empty), "%t", "Menu empty");
DisplayMenu(menu_weapons_weapons, client, MENU_TIME_FOREVER); AddMenuItem(menu_weapons_types, "empty", empty, ITEMDRAW_DISABLED);
}
// Set exit back button.
SetMenuExitBackButton(menu_weapons_types, true);
DisplayMenu(menu_weapons_types, client, MENU_TIME_FOREVER);
} }
/** /**
* Called when client selects option in the weapons list menu, and handles it. * Called when client selects option in the weapons list menu, and handles it.
* @param menu_weapons_main Handle of the menu being used. * @param menu_weapons_types Handle of the menu being used.
* @param action The action done on the menu (see menus.inc, enum MenuAction). * @param action The action done on the menu (see menus.inc, enum MenuAction).
* @param client The client index. * @param client The client index.
* @param slot The slot index selected (starting from 0). * @param slot The slot index selected (starting from 0).
*/ */
public WeaponsMenuWeaponsHandle(Handle:menu_weapons_weapons, MenuAction:action, client, slot) public WeaponsMenuTypesHandle(Handle:menu_weapons_types, MenuAction:action, client, slot)
{ {
// Client selected an option. // Client selected an option.
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
decl String:weapon[WEAPONS_MAX_LENGTH]; // Menu slot index is = weapon type index.
GetMenuItem(menu_weapons_weapons, slot, weapon, sizeof(weapon)); g_iCurWeaponType[client] = slot;
switch(curMenuWeapons[client]) // Send weapons of the selected type in a menu to client.
{ WeaponsMenuTypeWeapons(client);
// Client is restricting a single weapon.
case Weapon:
{
new WpnRestrictQuery:output;
if (!RestrictIsWeaponRestricted(weapon))
{
output = RestrictRestrict(weapon);
RestrictPrintRestrictOutput(client, output, weapon, false);
}
else
{
output = RestrictUnrestrict(weapon);
RestrictPrintUnrestrictOutput(client, output, weapon, false);
}
// Resend menu.
WeaponsMenuWeapons(client, curMenuWeapons[client]);
}
// Client is accessing a weapon group.
case WeaponGroup:
{
// Send weapon group menu.
WeaponsMenuWeaponGroup(client, weapon);
}
}
} }
// Client closed the menu. // Client closed the menu.
if (action == MenuAction_Cancel) if (action == MenuAction_Cancel)
@ -272,118 +158,141 @@ public WeaponsMenuWeaponsHandle(Handle:menu_weapons_weapons, MenuAction:action,
// Client hit "Exit" button. // Client hit "Exit" button.
else if (action == MenuAction_End) else if (action == MenuAction_End)
{ {
CloseHandle(menu_weapons_weapons); CloseHandle(menu_weapons_types);
} }
} }
WeaponsMenuWeaponGroup(client, const String:weapongroup[]) /**
* Sends a list of weapons of a certain type in a menu to the client.
* @param client The client index.
*/
WeaponsMenuTypeWeapons(client)
{ {
strcopy(curMenuGroup[client], WEAPONS_MAX_LENGTH, weapongroup);
// Create menu handle. // Create menu handle.
new Handle:menu_weapons_groupweapon = CreateMenu(WeaponsMenuWeaponGroupHandle); new Handle:menu_weapons_typeweapons = CreateMenu(WeaponsMenuTypeWeaponsHandle);
SetMenuTitle(menu_weapons_groupweapon, "%t\n ", "Weapons menu weapon group title", weapongroup); decl String:typename[WEAPONS_MAX_LENGTH];
RestrictWeaponTypeGetName(g_iCurWeaponType[client], typename, sizeof(typename));
SetMenuTitle(menu_weapons_typeweapons, "%t\n ", "Weapons menu types type title", typename);
decl String:restrictall[64]; decl String:restrictall[64];
decl String:unrestrictall[64]; decl String:unrestrictall[64];
Format(restrictall, sizeof(restrictall), "%t", "Weapons menu weapon group restrict all"); Format(restrictall, sizeof(restrictall), "%t", "Weapons menu types restrict all", typename);
Format(unrestrictall, sizeof(unrestrictall), "%t", "Weapons menu weapon group unrestrict all"); Format(unrestrictall, sizeof(unrestrictall), "%t", "Weapons menu types unrestrict all", typename);
if (RestrictIsGroupRestricted(weapongroup)) // Draw items as selectable only if not all weapons within the type are restricted or unrestricted.
{ AddMenuItem(menu_weapons_typeweapons, "restrictall", restrictall, MenuGetItemDraw(!RestrictIsTypeUniform(true, g_iCurWeaponType[client])));
AddMenuItem(menu_weapons_groupweapon, "restrictall", restrictall, ITEMDRAW_DISABLED); AddMenuItem(menu_weapons_typeweapons, "unrestrictall", unrestrictall, MenuGetItemDraw(!RestrictIsTypeUniform(false, g_iCurWeaponType[client])));
}
else
{
AddMenuItem(menu_weapons_groupweapon, "restrictall", restrictall);
}
if (RestrictIsGroupUnrestricted(weapongroup)) decl String:typeweapon[WEAPONS_MAX_LENGTH];
{ decl String:display[WEAPONS_MAX_LENGTH];
AddMenuItem(menu_weapons_groupweapon, "unrestrictall", unrestrictall, ITEMDRAW_DISABLED);
}
else
{
AddMenuItem(menu_weapons_groupweapon, "unrestrictall", unrestrictall);
}
decl String:groupweapon[WEAPONS_MAX_LENGTH]; // Get an array populated with all weapons of the given type.
decl String:display[WEAPONS_MAX_LENGTH + 1]; new Handle:arrayTypeWeapons;
new Handle:arrayGroupWeapons = INVALID_HANDLE; new count = RestrictGetTypeWeapons(g_iCurWeaponType[client], arrayTypeWeapons);
new size = RestrictCreateGroupWeaponsArray(arrayGroupWeapons, weapongroup);
// x = Array index. // x = Array index.
for (new x = 0; x < size; x++) for (new x = 0; x < count; x++)
{ {
GetArrayString(arrayGroupWeapons, x, groupweapon, sizeof(groupweapon)); // Get weapon index to check restricted status of.
new weaponindex = GetArrayCell(arrayTypeWeapons, x);
strcopy(display, sizeof(display), groupweapon); // Get name of weapon.
WeaponsGetName(weaponindex, typeweapon, sizeof(typeweapon));
strcopy(display, sizeof(display), typeweapon);
if (RestrictIsWeaponRestricted(groupweapon)) if (RestrictIsWeaponRestricted(weaponindex))
{ {
Format(display, sizeof(display), "%s*", groupweapon); Format(display, sizeof(display), "[%s]", typeweapon);
} }
AddMenuItem(menu_weapons_groupweapon, groupweapon, display); // Disable option if it isn't toggleable.
AddMenuItem(menu_weapons_typeweapons, typeweapon, display, MenuGetItemDraw(WeaponsGetToggleable(weaponindex)));
} }
// Kill the array handle. // Destroy the array handle.
CloseHandle(arrayGroupWeapons); CloseHandle(arrayTypeWeapons);
SetMenuExitBackButton(menu_weapons_groupweapon, true); // Set menu back button.
SetMenuExitBackButton(menu_weapons_typeweapons, true);
DisplayMenu(menu_weapons_groupweapon, client, MENU_TIME_FOREVER);
// Display menu to client.
DisplayMenu(menu_weapons_typeweapons, client, MENU_TIME_FOREVER);
} }
/** /**
* Called when client selects option in the weapon group menu, and handles it. * Called when client selects option in the weapon group menu, and handles it.
* @param menu_weapons_main Handle of the menu being used. * @param menu_weapons_typeweapons Handle of the menu being used.
* @param action The action done on the menu (see menus.inc, enum MenuAction). * @param action The action done on the menu (see menus.inc, enum MenuAction).
* @param client The client index. * @param client The client index.
* @param slot The slot index selected (starting from 0). * @param slot The slot index selected (starting from 0).
*/ */
public WeaponsMenuWeaponGroupHandle(Handle:menu_weapons_groupweapon, MenuAction:action, client, slot) public WeaponsMenuTypeWeaponsHandle(Handle:menu_weapons_typeweapons, MenuAction:action, client, slot)
{ {
// Client selected an option. // Client selected an option.
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
// Get name of current weapon type.
decl String:typename[WEAPONS_MAX_LENGTH];
RestrictWeaponTypeGetName(g_iCurWeaponType[client], typename, sizeof(typename));
new RestrictQuery:query;
new bool:single;
new bool:restrict;
decl String:returntarget[WEAPONS_MAX_LENGTH];
switch(slot) switch(slot)
{ {
case 0: case 0:
{ {
new WpnRestrictQuery:output = RestrictRestrict(curMenuGroup[client]); // Restrict all weapons of this type.
RestrictPrintRestrictOutput(client, output, curMenuGroup[client], false); restrict = true;
query = RestrictWeapon(true, typename, single, returntarget, sizeof(returntarget));
} }
case 1: case 1:
{ {
new WpnRestrictQuery:output = RestrictUnrestrict(curMenuGroup[client]); // Unrestrict all weapons of this type.
RestrictPrintUnrestrictOutput(client, output, curMenuGroup[client], false); restrict = false;
query = RestrictWeapon(false, typename, single, returntarget, sizeof(returntarget));
} }
default: default:
{ {
new WpnRestrictQuery:output; // Get weappon name.
decl String:typeweapon[WEAPONS_MAX_LENGTH];
GetMenuItem(menu_weapons_typeweapons, slot, typeweapon, sizeof(typeweapon));
decl String:groupweapon[WEAPONS_MAX_LENGTH]; // Get weapon index.
GetMenuItem(menu_weapons_groupweapon, slot, groupweapon, sizeof(groupweapon)); new weaponindex = WeaponsNameToIndex(typeweapon);
if (!RestrictIsWeaponRestricted(groupweapon)) // If weapon index is -1, then something went very wrong.
if (weaponindex == -1)
{ {
output = RestrictRestrict(groupweapon); CloseHandle(menu_weapons_typeweapons);
RestrictPrintRestrictOutput(client, output, groupweapon, false); }
// If weapon isn't restricted, then restrict it.
if (!RestrictIsWeaponRestricted(weaponindex))
{
// Restrict this weapon.
restrict = true;
query = RestrictWeapon(true, typeweapon, single, returntarget, sizeof(returntarget));
} }
else else
{ {
output = RestrictUnrestrict(groupweapon); // Unrestrict this weapon.
RestrictPrintUnrestrictOutput(client, output, groupweapon, false); restrict = false;
query = RestrictWeapon(false, typeweapon, single, returntarget, sizeof(returntarget));
} }
} }
} }
// Print query response.
RestrictPrintQueryResponse(client, query, single, restrict, returntarget);
// Resend menu. // Resend menu.
WeaponsMenuWeaponGroup(client, curMenuGroup[client]); WeaponsMenuTypeWeapons(client);
} }
// Client closed the menu. // Client closed the menu.
if (action == MenuAction_Cancel) if (action == MenuAction_Cancel)
@ -391,37 +300,38 @@ public WeaponsMenuWeaponGroupHandle(Handle:menu_weapons_groupweapon, MenuAction:
// Client hit "Back" button. // Client hit "Back" button.
if (slot == MenuCancel_ExitBack) if (slot == MenuCancel_ExitBack)
{ {
WeaponsMenuWeapons(client, curMenuWeapons[client]); WeaponsMenuTypes(client);
} }
} }
// Client hit "Exit" button. // Client hit "Exit" button.
else if (action == MenuAction_End) else if (action == MenuAction_End)
{ {
CloseHandle(menu_weapons_groupweapon); CloseHandle(menu_weapons_typeweapons);
} }
} }
/** /**
* Sends market options menu to client. * Sends ZMarket options menu to client.
* @param client The client index. * @param client The client index.
*/ */
WeaponsMenuMarket(client) WeaponsMenuZMarket(client)
{ {
// Create menu handle. // Create menu handle.
new Handle:menu_weapons_market = CreateMenu(WeaponsMenuMarketHandle); new Handle:menu_weapons_market = CreateMenu(WeaponsMenuZMarketHandle);
SetGlobalTransTarget(client); SetGlobalTransTarget(client);
SetMenuTitle(menu_weapons_market, "%t\n ", "Weapons menu market title"); SetMenuTitle(menu_weapons_market, "%t\n ", "Weapons menu zmarket title");
decl String:togglebuyzone[64]; decl String:buyzone[64];
decl String:buyzonesetting[8];
decl String:curSetting[8]; // Get "yes" or "no" settings from respective cvar.
ConfigBoolToSetting(GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]), curSetting, sizeof(curSetting)); ConfigBoolToSetting(GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]), buyzonesetting, sizeof(buyzonesetting));
Format(togglebuyzone, sizeof(togglebuyzone), "%t", "Weapons menu market toggle buyzone", curSetting); // Add options to menu.
Format(buyzone, sizeof(buyzone), "%t", "Weapons menu zmarket buyzone", buyzonesetting);
AddMenuItem(menu_weapons_market, "togglebuyzone", togglebuyzone); AddMenuItem(menu_weapons_market, "buyzone", buyzone);
// Create a "Back" button to the weapons main menu. // Create a "Back" button to the weapons main menu.
SetMenuExitBackButton(menu_weapons_market, true); SetMenuExitBackButton(menu_weapons_market, true);
@ -432,33 +342,29 @@ WeaponsMenuMarket(client)
/** /**
* Called when client selects option in the weapons main menu, and handles it. * Called when client selects option in the weapons main menu, and handles it.
* @param menu_weapons_main Handle of the menu being used. * @param menu_weapons_market Handle of the menu being used.
* @param action The action done on the menu (see menus.inc, enum MenuAction). * @param action The action done on the menu (see menus.inc, enum MenuAction).
* @param client The client index. * @param client The client index.
* @param slot The slot index selected (starting from 0). * @param slot The slot index selected (starting from 0).
*/ */
public WeaponsMenuMarketHandle(Handle:menu_weapons_market, MenuAction:action, client, slot) public WeaponsMenuZMarketHandle(Handle:menu_weapons_market, MenuAction:action, client, slot)
{ {
// Client selected an option. // Client selected an option.
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
switch(slot) switch(slot)
{ {
// Buyzone.
case 0: case 0:
{ {
if (GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE])) // Toggle cvar.
{ new bool:zmarketbuyzone = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]);
SetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE], false); SetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE], !zmarketbuyzone);
}
else
{
SetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE], true);
}
} }
} }
// Resend menu. // Resend menu.
WeaponsMenuMarket(client); WeaponsMenuZMarket(client);
} }
// Client closed the menu. // Client closed the menu.
if (action == MenuAction_Cancel) if (action == MenuAction_Cancel)

File diff suppressed because it is too large Load Diff

View File

@ -150,7 +150,7 @@ WeaponAlphaApplyWeaponAlpha(entity, alpha)
} }
// Get client's list of weapons. // Get client's list of weapons.
new weapons[WeaponsType]; new weapons[WeaponsSlot];
WeaponsGetClientWeapons(entity, weapons); WeaponsGetClientWeapons(entity, weapons);
// Loop through array slots and set alpha. // Loop through array slots and set alpha.

View File

@ -0,0 +1,81 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: weaponammo.inc
* Type: Core
* Description: API for all weaponammo-related functions.
*
* ============================================================================
*/
/**
* @section Variables to store ammo offset values.
*/
new g_iToolsClip1;
new g_iToolsClip2;
/**
* @endsection
*/
/**
* Find ammo-reserve-specific offsets here.
*/
WeaponAmmoOnOffsetsFound()
{
// If offset "m_iClip1" can't be found, then stop the plugin.
g_iToolsClip1 = FindSendPropInfo("CBaseCombatWeapon", "m_iClip1");
if (g_iToolsClip1 == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBaseCombatWeapon::m_iClip1\" was not found.");
}
// If offset "m_iClip2" can't be found, then stop the plugin.
g_iToolsClip2 = FindSendPropInfo("CBaseCombatWeapon", "m_iClip2");
if (g_iToolsClip2 == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBaseCombatWeapon::m_iClip2\" was not found.");
}
}
/**
* Set clip/reserve ammo on a weapon.
*
* @param weapon The weapon index.
* @param clip True sets clip ammo, false sets reserve.
* @param value The amount of ammo to set to.
* @param add (Optional) If true, the value is added to the weapon's current ammo count.
*/
stock WeaponAmmoSetClientAmmo(weapon, bool:clip, value, bool:add = false)
{
// Set variable to offset we are changing.
new ammooffset = clip ? g_iToolsClip1 : g_iToolsClip2;
// Initialize variable (value is 0)
new ammovalue;
// If we are adding, then update variable with current ammo value.
if (add)
{
ammovalue = WeaponAmmoGetClientAmmo(weapon, clip);
}
// Return ammo offset value.
SetEntData(weapon, ammooffset, ammovalue + value, _, true);
}
/**
* Get clip/reserve ammo on a weapon.
*
* @param weapon The weapon index.
* @param clip True gets clip ammo, false gets reserve.
*/
stock WeaponAmmoGetClientAmmo(weapon, bool:clip)
{
// Set variable to offset we are changing.
new ammooffset = clip ? g_iToolsClip1 : g_iToolsClip2;
// Return ammo offset value.
return GetEntData(weapon, ammooffset);
}

View File

@ -14,9 +14,6 @@
* Maximum length of a weapon name string * Maximum length of a weapon name string
*/ */
#define WEAPONS_MAX_LENGTH 32 #define WEAPONS_MAX_LENGTH 32
/**
* @endsection
*/
/** /**
* Number of weapon slots (For CS:S) * Number of weapon slots (For CS:S)
@ -24,27 +21,52 @@
#define WEAPONS_SLOTS_MAX 5 #define WEAPONS_SLOTS_MAX 5
/** /**
* Weapon types. * Weapon config data indexes.
*/ */
enum WeaponsType enum WeaponsData
{ {
Type_Invalid = -1, /** Invalid weapon (slot). */ WEAPONS_DATA_NAME = 0,
Type_Primary = 0, /** Primary weapon slot. */ WEAPONS_DATA_TYPE,
Type_Secondary = 1, /** Secondary weapon slot. */ WEAPONS_DATA_RESTRICTDEFAULT,
Type_Melee = 2, /** Melee (knife) weapon slot. */ WEAPONS_DATA_TOGGLEABLE,
Type_Projectile = 3, /** Projectile (grenades, flashbangs, etc) weapon slot. */ WEAPONS_DATA_AMMOTYPE,
Type_Explosive = 4, /** Explosive (c4) weapon slot. */ WEAPONS_DATA_AMMOPRICE,
WEAPONS_DATA_KNOCKBACK,
WEAPONS_DATA_ZMARKETPRICE,
WEAPONS_DATA_RESTRICTED,
} }
/** /**
* Keyvalue handle to store weapon data. * @endsection
*
* @redir config.inc
*/ */
/**
* 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/restrict"
#include "zr/weapons/weaponammo"
#include "zr/weapons/weaponalpha" #include "zr/weapons/weaponalpha"
#include "zr/weapons/markethandler" #include "zr/weapons/zmarket"
#include "zr/weapons/menu_weapons" #include "zr/weapons/menu_weapons"
/** /**
@ -52,10 +74,26 @@ enum WeaponsType
*/ */
WeaponsInit() WeaponsInit()
{ {
// Forward event to sub-module // Forward event to sub-modules.
RestrictInit(); 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. * Create commands related to weapons here.
*/ */
@ -65,34 +103,13 @@ WeaponsOnCommandsCreate()
RestrictOnCommandsCreate(); RestrictOnCommandsCreate();
} }
/**
* Clears weapon data.
*/
WeaponsClearData()
{
// Load weapon data
if (kvWeapons != INVALID_HANDLE)
{
CloseHandle(kvWeapons);
}
kvWeapons = CreateKeyValues("weapons");
}
/** /**
* Loads weapon data from file. * Loads weapon data from file.
*/ */
WeaponsLoad() WeaponsLoad()
{ {
// Clear weapon data. // Register config file.
WeaponsClearData(); ConfigRegisterConfig(File_Weapons, Structure_Keyvalue, CONFIG_FILE_ALIAS_WEAPONS);
// 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);
// If module is disabled, then stop. // If module is disabled, then stop.
new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]); new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]);
@ -101,6 +118,10 @@ WeaponsLoad()
return; 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 file doesn't exist, then log and stop.
if (!exists) if (!exists)
{ {
@ -110,46 +131,121 @@ WeaponsLoad()
return; return;
} }
// Put file data into memory. // Set the path to the config file.
FileToKeyValues(kvWeapons, pathweapons); 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. // 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. // Set config data.
ConfigSetConfigLoaded(ConfigWeapons, true); ConfigSetConfigLoaded(File_Weapons, true);
ConfigSetConfigHandle(ConfigWeapons, kvWeapons); ConfigSetConfigReloadFunc(File_Weapons, GetFunctionByName(GetMyHandle(), "WeaponsOnConfigReload"));
ConfigSetConfigHandle(File_Weapons, arrayWeapons);
// Forward event to sub-module. // Forward event to sub-modules
RestrictLoad(); RestrictLoad();
} }
/** /**
* Called when configs are being reloaded. * Caches weapon data from file into arrays.
* * Make sure the file is loaded before (ConfigLoadConfig) to prep array structure.
* @param config The config being reloaded. (only if 'all' is false)
*/ */
public WeaponsOnConfigReload(ConfigFile:config) WeaponsCacheData()
{ {
// Reload weapons config. // Get config's file path.
if (config == ConfigWeapons) 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); // Reload weapons config.
if (!KvGotoFirstSubKey(kvWeapons)) WeaponsLoad();
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Weapons", "Config Validation", "No weapons listed in weapons.txt.");
}
} }
/** /**
* Client is joining the server. * Client is joining the server.
* *
@ -195,154 +291,173 @@ WeaponsOnRoundEnd()
} }
/** /**
* Creates an array of all listed weapons in weapons.txt. * Weapon data reading API.
* @param arrayWeapons The handle of the array, don't forget to call CloseHandle
* on it when finished!
* @return The size of the array.
*/ */
stock WeaponsCreateWeaponArray(&Handle:arrayWeapons, maxlen = WEAPONS_MAX_LENGTH)
/**
* Clear cache for a given weapon.
*
* @param index The weapon index.
*/
WeaponsClearCache(index)
{ {
// Initialize array handle. // Get array handle of weapon at given index.
arrayWeapons = CreateArray(maxlen); new Handle:hWeapon = GetArrayCell(arrayWeapons, index);
new count = 0;
// Reset keyvalue's traveral stack. // Clear array.
KvRewind(kvWeapons); ClearArray(hWeapon);
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;
} }
/** /**
* 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. * @param weapon The weapon name.
* @return Returns true if valid, false it not. * @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. return (WeaponsNameToIndex(weapon) != -1);
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;
} }
/** /**
* Looks up a weapon in weapons.txt and returns exact display name. * Gets the name of a weapon at a given index.
* @param weapon The weapon name. * @param index The weapon index.
* @param display Returns with the display name, is not changed if weapon is invalid. * @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. // Get array handle of weapon at given index.
KvRewind(kvWeapons); new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
if (KvGotoFirstSubKey(kvWeapons))
{ // Get weapon name.
decl String:validweapon[WEAPONS_MAX_LENGTH]; GetArrayString(arrayWeapon, _:WEAPONS_DATA_NAME, weapon, maxlen);
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));
}
} }
/** /**
* Checks if a weapon restriction can be toggled by the admin menu. * Gets the type of a weapon at a given index.
* @param weapon The weapon name. * @param index The weapon index.
* @return Returns true if restricted, false it not. * @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. // Get array handle of weapon at given index.
KvRewind(kvWeapons); new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
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));
}
return false; // Get weapon type.
GetArrayString(arrayWeapon, _:WEAPONS_DATA_TYPE, type, maxlen);
} }
/** /**
* Returns knockback multiplier of the weapon. * Gets if a weapon is restricted by default.
* @param weapon The weapon name. * @param index The weapon index.
* @return The float value of the knockback multiplier, 1.0 if not found. * @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. // Get array handle of weapon at given index.
KvRewind(kvWeapons); new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
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; // 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. * @param weapons The weapon index array.
* -1 if no weapon in slot. * -1 if no weapon in slot.
*/ */
stock WeaponsGetClientWeapons(client, weapons[WeaponsType]) stock WeaponsGetClientWeapons(client, weapons[WeaponsSlot])
{ {
// x = weapon slot. // x = weapon slot.
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++) for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
@ -384,10 +499,10 @@ stock WeaponsGetDeployedWeaponIndex(client)
* @param client The client index. * @param client The client index.
* @return The slot number of deployed weapon. * @return The slot number of deployed weapon.
*/ */
stock WeaponsType:WeaponsGetDeployedWeaponSlot(client) stock WeaponsSlot:WeaponsGetDeployedWeaponSlot(client)
{ {
// Get all client's weapon indexes. // Get all client's weapon indexes.
new weapons[WeaponsType]; new weapons[WeaponsSlot];
WeaponsGetClientWeapons(client, weapons); WeaponsGetClientWeapons(client, weapons);
// Get client's deployed weapon. // Get client's deployed weapon.
@ -404,7 +519,7 @@ stock WeaponsType:WeaponsGetDeployedWeaponSlot(client)
{ {
if (weapons[x] == deployedweapon) if (weapons[x] == deployedweapon)
{ {
return x; return WeaponsSlot:x;
} }
} }

View File

@ -0,0 +1,47 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File:
* Type: Module
* Description:
*
* ============================================================================
*/
/**
* Variable to store buyzone offset value.
*/
new g_iToolsInBuyZone;
/**
* Initialize market data.
*/
ZMarketInit()
{
}
/**
* Find ZMarket-specific offsets here.
*/
ZMarketOnOffsetsFound()
{
// If offset "m_bInBuyZone" can't be found, then stop the plugin.
g_iToolsInBuyZone = FindSendPropInfo("CCSPlayer", "m_bInBuyZone");
if (g_iToolsInBuyZone == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CCSPlayer::m_bInBuyZone\" was not found.");
}
}
/**
* Checks if a client is in a buyzone.
*
* @param client The client index.
*/
stock bool:ZMarketIsClientInBuyZone(client)
{
// Return if client is in buyzone.
return bool:GetEntData(client, g_iToolsInBuyZone);
}

View File

@ -10,9 +10,6 @@
* ============================================================================ * ============================================================================
*/ */
#include "include/adminmenu.inc"
//new curMenuClass[MAXPLAYERS + 1];
bool:ZRAdminMenu(client) bool:ZRAdminMenu(client)
{ {
if (!ZRIsClientAdmin(client)) if (!ZRIsClientAdmin(client))
@ -27,35 +24,34 @@ bool:ZRAdminMenu(client)
SetMenuTitle(menu_zadmin, "%t\n ", "!zadmin main title"); SetMenuTitle(menu_zadmin, "%t\n ", "!zadmin main title");
decl String:knockbackm[64]; //decl String:knockbackm[64];
decl String:knockback[64]; //decl String:knockback[64];
decl String:nvgs[64]; //decl String:infect[64];
decl String:infect[64]; //decl String:zspawn[64];
decl String:zspawn[64]; //decl String:ztele[64];
decl String:ztele[64];
decl String:weapons[64]; decl String:weapons[64];
decl String:logflags[64]; //decl String:logflags[64];
Format(knockbackm, sizeof(knockbackm), "%t", "!zadmin main knockbackm"); //Format(knockbackm, sizeof(knockbackm), "%t", "!zadmin main knockbackm");
Format(knockback, sizeof(knockback), "%t", "!zadmin main knockback"); //Format(knockback, sizeof(knockback), "%t", "!zadmin main knockback");
Format(nvgs, sizeof(nvgs), "%t", "!zadmin main nvgs"); //Format(infect, sizeof(infect), "%t", "!zadmin main infect");
Format(infect, sizeof(infect), "%t", "!zadmin main infect"); //Format(zspawn, sizeof(zspawn), "%t", "!zadmin main spawn");
Format(zspawn, sizeof(zspawn), "%t", "!zadmin main spawn"); //Format(ztele, sizeof(ztele), "%t", "!zadmin main tele");
Format(ztele, sizeof(ztele), "%t", "!zadmin main tele");
Format(weapons, sizeof(weapons), "%t", "!zadmin main weapons"); Format(weapons, sizeof(weapons), "%t", "!zadmin main weapons");
Format(logflags, sizeof(logflags), "%t", "!zadmin main logflags"); //Format(logflags, sizeof(logflags), "%t", "!zadmin main logflags");
AddMenuItem(menu_zadmin, "knockbackm", knockbackm, ITEMDRAW_DISABLED); //AddMenuItem(menu_zadmin, "knockbackm", knockbackm, ITEMDRAW_DISABLED);
AddMenuItem(menu_zadmin, "knockback", knockback, ITEMDRAW_DISABLED); //AddMenuItem(menu_zadmin, "knockback", knockback, ITEMDRAW_DISABLED);
AddMenuItem(menu_zadmin, "nvgs", nvgs, ITEMDRAW_DISABLED); //AddMenuItem(menu_zadmin, "infect", infect);
AddMenuItem(menu_zadmin, "infect", infect); //AddMenuItem(menu_zadmin, "zspawn", zspawn);
AddMenuItem(menu_zadmin, "zspawn", zspawn); //AddMenuItem(menu_zadmin, "ztele", ztele, ITEMDRAW_DISABLED);
AddMenuItem(menu_zadmin, "ztele", ztele, ITEMDRAW_DISABLED);
AddMenuItem(menu_zadmin, "weapons", weapons); AddMenuItem(menu_zadmin, "weapons", weapons);
AddMenuItem(menu_zadmin, "logflags", logflags); //AddMenuItem(menu_zadmin, "logflags", logflags);
// Set "Back" button.
SetMenuExitBackButton(menu_zadmin, true); SetMenuExitBackButton(menu_zadmin, true);
// Send menu to client.
DisplayMenu(menu_zadmin, client, MENU_TIME_FOREVER); DisplayMenu(menu_zadmin, client, MENU_TIME_FOREVER);
return true; return true;
@ -67,45 +63,21 @@ public ZRAdminMenuHandle(Handle:menu_admin, MenuAction:action, client, slot)
{ {
switch(slot) switch(slot)
{ {
// Weapon management.
case 0: case 0:
{
//ZRKnockbackMMenu(client);
}
case 1:
{
//ZRClassSelectMenu(client);
}
case 2:
{
//ZRNVGSMenu(client);
}
case 3:
{
ZRInfectMenu(client);
}
case 4:
{
ZRSpawnAll(client);
}
case 5:
{
ZRZTeleMenu(client);
}
case 6:
{ {
WeaponsMenuMain(client); WeaponsMenuMain(client);
} }
case 7:
{
ZRLogFlagsMenu(client);
}
} }
// TODO: Resend menu if feature is disabled or unopenable.
} }
if (action == MenuAction_Cancel) if (action == MenuAction_Cancel)
{ {
if (slot == MenuCancel_ExitBack) if (slot == MenuCancel_ExitBack)
{ {
// Exit back to main menu.
MenuMain(client); MenuMain(client);
} }
} }
@ -145,9 +117,9 @@ public ZRAdminMenuHandle(Handle:menu_admin, MenuAction:action, client, slot)
SetMenuExitBackButton(menu_knockbackm, true); SetMenuExitBackButton(menu_knockbackm, true);
DisplayMenu(menu_knockbackm, client, MENU_TIME_FOREVER); DisplayMenu(menu_knockbackm, client, MENU_TIME_FOREVER);
} }*/
public ZRKnockbackMHandle(Handle:menu_knockbackm, MenuAction:action, client, slot) /*public ZRKnockbackMHandle(Handle:menu_knockbackm, MenuAction:action, client, slot)
{ {
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
@ -186,9 +158,9 @@ public ZRKnockbackMHandle(Handle:menu_knockbackm, MenuAction:action, client, slo
{ {
CloseHandle(menu_knockbackm); CloseHandle(menu_knockbackm);
} }
} }*/
ZRClassSelectMenu(client) /*ZRClassSelectMenu(client)
{ {
new Handle:menu_class = CreateMenu(ZRClassSelectHandle); new Handle:menu_class = CreateMenu(ZRClassSelectHandle);
@ -204,9 +176,9 @@ ZRClassSelectMenu(client)
SetMenuExitBackButton(menu_class, true); SetMenuExitBackButton(menu_class, true);
DisplayMenu(menu_class, client, MENU_TIME_FOREVER); DisplayMenu(menu_class, client, MENU_TIME_FOREVER);
} }*/
public ZRClassSelectHandle(Handle:menu_class, MenuAction:action, client, slot) /*public ZRClassSelectHandle(Handle:menu_class, MenuAction:action, client, slot)
{ {
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
@ -224,9 +196,9 @@ public ZRClassSelectHandle(Handle:menu_class, MenuAction:action, client, slot)
{ {
CloseHandle(menu_class); CloseHandle(menu_class);
} }
} }*/
ZRClassKnockbackMenu(client, classindex) /*ZRClassKnockbackMenu(client, classindex)
{ {
new Handle:menu_knockback = CreateMenu(ZRClassKnockbackHandle); new Handle:menu_knockback = CreateMenu(ZRClassKnockbackHandle);
@ -257,9 +229,9 @@ ZRClassKnockbackMenu(client, classindex)
SetMenuExitBackButton(menu_knockback, true); SetMenuExitBackButton(menu_knockback, true);
DisplayMenu(menu_knockback, client, MENU_TIME_FOREVER); DisplayMenu(menu_knockback, client, MENU_TIME_FOREVER);
} }*/
public ZRClassKnockbackHandle(Handle:menu_knockback, MenuAction:action, client, slot) /*public ZRClassKnockbackHandle(Handle:menu_knockback, MenuAction:action, client, slot)
{ {
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
@ -296,71 +268,9 @@ public ZRClassKnockbackHandle(Handle:menu_knockback, MenuAction:action, client,
{ {
CloseHandle(menu_knockback); CloseHandle(menu_knockback);
} }
}
ZRNVGSMenu(client)
{
new Handle:menu_nvgs = CreateMenu(ZRNVGSHandle);
new curnvgs = GetConVarInt(g_hCvarsList[CVAR_ZOMBIE_NVGS]);
SetGlobalTransTarget(client);
SetMenuTitle(menu_nvgs, "%t\n ", "!zadmin nvgs title", curnvgs);
decl String:nooverride[64];
decl String:disable[64];
decl String:enable[64];
Format(nooverride, sizeof(nooverride), "%t", "!zadmin nvgs no override");
Format(disable, sizeof(disable), "%t", "!zadmin nvgs disable");
Format(enable, sizeof(enable), "%t", "!zadmin nvgs enable");
AddMenuItem(menu_nvgs, "nooverride", nooverride);
AddMenuItem(menu_nvgs, "disable", disable);
AddMenuItem(menu_nvgs, "enable", enable);
SetMenuExitBackButton(menu_nvgs, true);
DisplayMenu(menu_nvgs, client, MENU_TIME_FOREVER);
}
public ZRNVGSHandle(Handle:menu_nvgs, MenuAction:action, client, slot)
{
if (action == MenuAction_Select)
{
switch(slot)
{
case 0:
{
SetConVarInt(g_hCvarsList[CVAR_ZOMBIE_NVGS], -1);
ZRNVGSMenu(client);
}
case 1:
{
SetConVarInt(g_hCvarsList[CVAR_ZOMBIE_NVGS], 0);
ZRNVGSMenu(client);
}
case 2:
{
SetConVarInt(g_hCvarsList[CVAR_ZOMBIE_NVGS], 1);
ZRNVGSMenu(client);
}
}
}
if (action == MenuAction_Cancel)
{
if (slot == MenuCancel_ExitBack)
{
ZRAdminMenu(client);
}
}
if (action == MenuAction_End)
{
CloseHandle(menu_nvgs);
}
}*/ }*/
ZRInfectMenu(client) /*ZRInfectMenu(client)
{ {
new Handle:menu_infect = CreateMenu(ZRInfectHandle); new Handle:menu_infect = CreateMenu(ZRInfectHandle);
@ -373,9 +283,9 @@ ZRInfectMenu(client)
SetMenuExitBackButton(menu_infect, true); SetMenuExitBackButton(menu_infect, true);
DisplayMenu(menu_infect, client, MENU_TIME_FOREVER); DisplayMenu(menu_infect, client, MENU_TIME_FOREVER);
} }*/
public ZRInfectHandle(Handle:menu_infect, MenuAction:action, client, slot) /*public ZRInfectHandle(Handle:menu_infect, MenuAction:action, client, slot)
{ {
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
@ -417,9 +327,9 @@ public ZRInfectHandle(Handle:menu_infect, MenuAction:action, client, slot)
{ {
CloseHandle(menu_infect); CloseHandle(menu_infect);
} }
} }*/
ZRSpawnAll(client) /*ZRSpawnAll(client)
{ {
// x = client index. // x = client index.
for (new x = 1; x < MaxClients; x++) for (new x = 1; x < MaxClients; x++)
@ -430,9 +340,9 @@ ZRSpawnAll(client)
} }
} }
ZRAdminMenu(client); ZRAdminMenu(client);
} }*/
ZRZTeleMenu(client) /*ZRZTeleMenu(client)
{ {
new Handle:menu_ztele = CreateMenu(ZRTeleHandle); new Handle:menu_ztele = CreateMenu(ZRTeleHandle);
@ -457,9 +367,9 @@ ZRZTeleMenu(client)
SetMenuExitBackButton(menu_ztele, true); SetMenuExitBackButton(menu_ztele, true);
DisplayMenu(menu_ztele, client, MENU_TIME_FOREVER); DisplayMenu(menu_ztele, client, MENU_TIME_FOREVER);
} }*/
public ZRTeleHandle(Handle:menu_ztele , MenuAction:action, client, slot) /*public ZRTeleHandle(Handle:menu_ztele , MenuAction:action, client, slot)
{ {
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
@ -494,9 +404,9 @@ public ZRTeleHandle(Handle:menu_ztele , MenuAction:action, client, slot)
{ {
CloseHandle(menu_ztele); CloseHandle(menu_ztele);
} }
} }*/
ZRLogFlagsMenu(client) /*ZRLogFlagsMenu(client)
{ {
new Handle:menu_log_flags = CreateMenu(ZRLogFlagsMenuHandle); new Handle:menu_log_flags = CreateMenu(ZRLogFlagsMenuHandle);
@ -515,9 +425,9 @@ ZRLogFlagsMenu(client)
SetMenuExitBackButton(menu_log_flags, true); SetMenuExitBackButton(menu_log_flags, true);
DisplayMenu(menu_log_flags, client, MENU_TIME_FOREVER); DisplayMenu(menu_log_flags, client, MENU_TIME_FOREVER);
} }*/
public ZRLogFlagsMenuHandle(Handle:menu_log_flags, MenuAction:action, client, slot) /*public ZRLogFlagsMenuHandle(Handle:menu_log_flags, MenuAction:action, client, slot)
{ {
if (action == MenuAction_Select) if (action == MenuAction_Select)
{ {
@ -536,4 +446,4 @@ public ZRLogFlagsMenuHandle(Handle:menu_log_flags, MenuAction:action, client, sl
{ {
CloseHandle(menu_log_flags); CloseHandle(menu_log_flags);
} }
} }*/

View File

@ -1,22 +0,0 @@
RemoveObjectives()
{
decl String:classname[64];
new maxentities = GetMaxEntities();
for (new x = 0; x <= maxentities; x++)
{
if(!IsValidEdict(x))
{
continue;
}
GetEdictClassname(x, classname, sizeof(classname));
if( StrEqual(classname, "func_bomb_target") ||
StrEqual(classname, "func_hostage_rescue") ||
StrEqual(classname, "c4") ||
StrEqual(classname, "hostage_entity"))
{
RemoveEdict(x);
}
}
}

View File

@ -1,46 +0,0 @@
Section content is listed in order of importance. Some of these can be ideas too.
---- CRITICAL/IMPORTANT ----
---- NORMAL/GAMEPLAY ----
* Fix zvision not displayed if classes are disabled.
* Make admin commands to get or set player classes:
zr_classes_set <classname> <target>
zr_classes_get <#userid|name>
* Make it possible to disable certain classes on certain maps. Only specify the
class name to read the value:
zr_class_enabled <classname> [<0/1>]
* Per-weapon clip sizes. A new module with detailed control of ammo (modes, limits, timers).
* Remove dead bodies to improve performance (CVAR).
* More grenades for humans (probably with a buy-command or something). It's on
the edge to become a RPG-like feature.
* Super features for both zombies and humans:
- Humans: No fall damage for X seconds. X limits per round.
- Zombies: No knockback/damage for X seconds. X limits per round.
* Make a admin command to read and write settings to a spesific class,
using key/value. Integrate it with the zr_admin menu.
* Knockback presets (integrated into zombie admin menu).
Temporary do many changes on the zombies (by executing configs). Useful
settings or fun settings. SourceMod already has a execute config menu, but it
would be better if this was integrated in ZR.
* zombie.inc:KnockBack / cvars.inc
Make a CVAR for adjusting shotgun/hegrenade knockback boost.
* Validate ALL configs and cvars while loading the plugin. Log messages and unload ZR (or use default) if invalid data is found.
* Make a jetpack feature.
* Fix some zombies not able to zombify some humans when using the infect
command before the first zombie. (make him a mother zombie, kill infect timer,
set some switches)