Made a anticamp feature with custom hurt volumes. Reformatted changes.txt.

This commit is contained in:
richard 2009-01-19 22:45:58 +01:00
parent e3f4b4e400
commit 972136b859
7 changed files with 593 additions and 70 deletions

View File

@ -1,3 +1,7 @@
2009.01.18 - 2.5.1.24
* Created a anticamp feature that give players damage at a specified interval in custom defined volumes. Only affects humans.
* Re-formatted changes.txt.
2009.01.17 - 2.5.1.23 2009.01.17 - 2.5.1.23
* Fixed teleport location text to display as float values instead of decimal. * Fixed teleport location text to display as float values instead of decimal.

View File

@ -1,7 +1,10 @@
Behaviour changes from version 2.5.1 Changes from Zombie: Reloaded 2.5.1
===================================== ====================================
* Support for alpha values in classes. New values in classes.txt (per class): Alpha values (transparency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for alpha values in classes. New values in classes.txt (per class):
Key: Value: Default: Description: Key: Value: Default: Description:
alpha_spawn <0-255> 255 initial alpha value (0 = transparent) alpha_spawn <0-255> 255 initial alpha value (0 = transparent)
@ -9,31 +12,73 @@ Behaviour changes from version 2.5.1
alpha_damage <damage> 0 how much damage to do before alpha_damage <damage> 0 how much damage to do before
alpha_damaged take effect alpha_damaged take effect
* If classes are enabled the zr_zombie_knockback cvar is used as a multiplier. Knockback 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.
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 knockback = zr_zombie_knockback * class knockback
* Spawn protection makes the players invisible and move faster, and cannot be Full spawn protection
infected during protecting time. A centered counter shows the time remaining. ~~~~~~~~~~~~~~~~~~~~~~
* Support for overrriding class nvgs with the zr_zombie_nvgs cvar: Spawn protection makes the players invisible and move faster, and cannot be
Generally, any non-zero value is considered as on. 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: Value: Description:
-1 no override (use value in classes.txt) / nvgs on -1 no override (use value in classes.txt) / nvgs on
0 never give nvgs 0 never give nvgs
1 always give nvgs 1 always give nvgs
* Setting default class with a cvar. Works with per-map configs. 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.
zr_classes_default <classname> zr_classes_default <classname>
* Zombie admin menu. Basic zombie admin commands like adjusting knockback, nvgs, Zombie admin menu
infecting players and spawn everyone. Knockback changes are applied instantly, ~~~~~~~~~~~~~~~~~~
useful for fine tuning live. Note that the changes are not saved. They will be
reset on map change. In the future this menu might save the changes. 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 Knockback multiplier
- Fine tune the knockback multiplier. - Fine tune the knockback multiplier.
@ -53,8 +98,11 @@ Behaviour changes from version 2.5.1
(more zombie admin stuff might come...) (more zombie admin stuff might come...)
* Console commands zr_set_class_knockback and zr_get_class_knockback. Changes Set (and get) class knockback
are not saved. They will be reset on map change. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Set or get knockback from a class. Changes are not saved. They will be reset on
map change.
zr_set_class_knockback <classname> <knockback> zr_set_class_knockback <classname> <knockback>
- Sets knockback to a specified class. Useful when using per-map configs to - Sets knockback to a specified class. Useful when using per-map configs to
@ -64,4 +112,7 @@ Behaviour changes from version 2.5.1
- Prints the current knockback of a class to the client/server console. - 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. Using the zombie admin menu to read a knockback value is easier sometimes.
* Other minior and major bug fixes. See changelog.txt. More stuff
~~~~~~~~~~~
Other minior and major bug fixes. See changelog.txt.

View File

@ -225,6 +225,17 @@
"ru" "Неплохая попытка n00b!" "ru" "Неплохая попытка n00b!"
} }
"Unfair camping"
{
"en" "This area is marked as unfair. Move, go through or die..."
}
"Unfair camper slayed"
{
"#format" "{1:s},{2:d}"
"en" "Killed %s due to camping in a unfair area (id: %d)."
}
"DX90 not supported" "DX90 not supported"
{ {
"#format" "{1:d},{2:d}" "#format" "{1:d},{2:d}"

View File

@ -15,7 +15,7 @@
#undef REQUIRE_PLUGIN #undef REQUIRE_PLUGIN
#include <market> #include <market>
#define VERSION "2.5.1.23" #define VERSION "2.5.1.24"
#include "zr/zombiereloaded" #include "zr/zombiereloaded"
#include "zr/global" #include "zr/global"
@ -26,6 +26,7 @@
#include "zr/classes" #include "zr/classes"
#include "zr/models" #include "zr/models"
#include "zr/overlays" #include "zr/overlays"
#include "zr/anticamp"
#include "zr/teleport" #include "zr/teleport"
#include "zr/zombie" #include "zr/zombie"
#include "zr/menu" #include "zr/menu"
@ -123,6 +124,13 @@ public OnMapStart()
pClass[i] = classindex; pClass[i] = classindex;
} }
} }
Anticamp_Startup();
}
public OnMapEnd()
{
Anticamp_Disable();
} }
public OnConfigsExecuted() public OnConfigsExecuted()

437
src/zr/anticamp.inc Normal file
View File

@ -0,0 +1,437 @@
/**
* ====================
* Zombie:Reloaded
* File: anticamp.inc
* Authors: Richard Helgeby
* ====================
*/
#define MAX_VOLUMES 32
enum volume
{
Float:x_min,
Float:x_max,
Float:y_min,
Float:y_max,
Float:z_min,
Float:z_max,
volume_damage,
Float:volume_interval,
Handle:volume_timer,
bool:volume_in_use
}
new volumes[MAX_VOLUMES][volume];
new volume_count;
new Float:player_loc[MAXPLAYERS][3];
new Handle:hUpdateTimer;
Anticamp_Startup(bool:no_reset = false)
{
new Float:interval = GetConVarFloat(gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL]);
// Create timer for updating player locations.
if (hUpdateTimer != INVALID_HANDLE)
{
KillTimer(hUpdateTimer);
hUpdateTimer = INVALID_HANDLE;
}
if (interval > 0.0)
{
hUpdateTimer = CreateTimer(interval, Event_UpdatePlayerLocations, 0, TIMER_REPEAT);
}
if (no_reset)
{
// Start existing hurt timers.
for (new vol_index = 0; vol_index < MAX_VOLUMES; vol_index++)
{
if (volumes[vol_index][volume_in_use])
{
if (volumes[vol_index][volume_timer] != INVALID_HANDLE)
{
KillTimer(volumes[vol_index][volume_timer]);
}
volumes[vol_index][volume_timer] = CreateTimer(volumes[vol_index][volume_interval], Event_HurtPlayers, vol_index, TIMER_REPEAT);
}
}
}
else
{
ResetVolumes();
}
}
Anticamp_Disable()
{
// Kill update timer.
if (hUpdateTimer != INVALID_HANDLE)
{
KillTimer(hUpdateTimer);
hUpdateTimer = INVALID_HANDLE;
}
// Kill hurt timers.
for (new vol = 0; vol < MAX_VOLUMES; vol++)
{
if (volumes[vol][volume_timer] != INVALID_HANDLE)
{
KillTimer(volumes[vol][volume_timer]);
volumes[vol][volume_timer] = INVALID_HANDLE;
}
}
}
public UpdateIntervalHook(Handle:convar, const String:oldValue[], const String:newValue[])
{
new Float:interval = StringToFloat(newValue);
if (hUpdateTimer != INVALID_HANDLE)
{
KillTimer(hUpdateTimer);
hUpdateTimer = INVALID_HANDLE;
}
if (interval > 0.0)
{
hUpdateTimer = CreateTimer(interval, Event_UpdatePlayerLocations, 0, TIMER_REPEAT);
}
}
public AnticampHook(Handle:convar, const String:oldValue[], const String:newValue[])
{
new anticamp_enabled = StringToInt(newValue);
if (anticamp_enabled)
{
Anticamp_Startup(true);
}
else
{
Anticamp_Disable();
}
}
public Action:Command_AnticampCreateVolume(client, argc)
{
// Get a unused volume index.
new vol_index = GetFreeVolumeIndex();
if (vol_index == -1)
{
ReplyToCommand(client, "Maximum volumes reached. Max: %d", MAX_VOLUMES);
return Plugin_Handled;
}
// Check arguments.
if (argc < 8)
{
ReplyToCommand(client, "Too few parameters specified. Usage: zr_anticamp_create_volume <damage> <interval> <x1> <y1> <z1> <x2> <y2> <z2>");
return Plugin_Handled;
}
decl String:arg_buffer[32];
new vol_damage;
new Float:vol_interval;
new Float:x1;
new Float:y1;
new Float:z1;
new Float:x2;
new Float:y2;
new Float:z2;
// Get arguments.
GetCmdArg(1, arg_buffer, sizeof(arg_buffer));
vol_damage = StringToInt(arg_buffer);
GetCmdArg(2, arg_buffer, sizeof(arg_buffer));
vol_interval = StringToFloat(arg_buffer);
GetCmdArg(3, arg_buffer, sizeof(arg_buffer));
x1 = StringToFloat(arg_buffer);
GetCmdArg(4, arg_buffer, sizeof(arg_buffer));
y1 = StringToFloat(arg_buffer);
GetCmdArg(5, arg_buffer, sizeof(arg_buffer));
z1 = StringToFloat(arg_buffer);
GetCmdArg(6, arg_buffer, sizeof(arg_buffer));
x2 = StringToFloat(arg_buffer);
GetCmdArg(7, arg_buffer, sizeof(arg_buffer));
y2 = StringToFloat(arg_buffer);
GetCmdArg(8, arg_buffer, sizeof(arg_buffer));
z2 = StringToFloat(arg_buffer);
// Check damage.
if (vol_damage == 0)
{
ReplyToCommand(client, "The damage specified is zero or invalid.");
return Plugin_Handled;
}
// Check interval.
if (vol_interval <= 0.0)
{
ReplyToCommand(client, "The interval specified is zero or invalid.");
return Plugin_Handled;
}
// Check if both locations are equal.
if (FloatCompare(x1, x2) == 0)
{
if (FloatCompare(y1, y2) == 0)
{
if (FloatCompare(z1, z2) == 0)
{
ReplyToCommand(client, "Cannot add hurt volume. Both locations are equal.");
return Plugin_Handled;
}
}
}
// Sort out max and min values.
if (FloatCompare(x1, x2) == 1)
{
volumes[vol_index][x_max] = x1;
volumes[vol_index][x_min] = x2;
}
else
{
volumes[vol_index][x_max] = x2;
volumes[vol_index][x_min] = x1;
}
if (FloatCompare(y1, y2) == 1)
{
volumes[vol_index][y_max] = y1;
volumes[vol_index][y_min] = y2;
}
else
{
volumes[vol_index][y_max] = y2;
volumes[vol_index][y_min] = y1;
}
if (FloatCompare(z1, z2) == 1)
{
volumes[vol_index][z_max] = z1;
volumes[vol_index][z_min] = z2;
}
else
{
volumes[vol_index][z_max] = z2;
volumes[vol_index][z_min] = z1;
}
volumes[vol_index][volume_damage] = vol_damage;
volumes[vol_index][volume_interval] = vol_interval;
volumes[vol_index][volume_timer] = CreateTimer(vol_interval, Event_HurtPlayers, vol_index, TIMER_REPEAT);
volumes[vol_index][volume_in_use] = true;
ReplyToCommand(client, "Volume created:\nid: %d\nx min:%f\ny min:%f\nz min:%f\nx max:%f\ny max:%f\nz max:%f",
vol_index,
volumes[vol_index][x_min],
volumes[vol_index][y_min],
volumes[vol_index][z_min],
volumes[vol_index][x_max],
volumes[vol_index][y_max],
volumes[vol_index][z_max]);
volume_count++;
return Plugin_Handled;
}
public Action:Command_AnticampRemoveVolume(client, argc)
{
new vol_index;
decl String:arg_buffer[32];
new Handle:vol_timer;
if (argc < 1)
{
ReplyToCommand(client, "Volume ID not specified. Usage: zr_anticamp_remove_volume <volume id>");
return Plugin_Handled;
}
GetCmdArg(1, arg_buffer, sizeof(arg_buffer));
vol_index = StringToInt(arg_buffer);
if (IsValidVolume(vol_index))
{
vol_timer = volumes[vol_index][volume_timer];
if (vol_timer != INVALID_HANDLE)
{
KillTimer(vol_timer);
volumes[vol_index][volume_timer] = INVALID_HANDLE;
}
volumes[vol_index][volume_in_use] = false;
ReplyToCommand(client, "Removed volume %d.", vol_index);
}
else
{
ReplyToCommand(client, "Invalid volume ID.");
return Plugin_Handled;
}
return Plugin_Handled;
}
public Action:Command_AnticampList(client, argc)
{
decl String:buffer[2048];
decl String:line[192];
buffer[0] = 0;
StrCat(buffer, sizeof(buffer), "id damage interval x_min y_min z_min x_max y_max z_max\n");
for (new vol_index = 0; vol_index < MAX_VOLUMES; vol_index++)
{
if (volumes[vol_index][volume_in_use])
{
Format(line, sizeof(line), "%d %d %f %f %f %f %f %f %f\n",
vol_index,
volumes[vol_index][volume_damage],
volumes[vol_index][volume_interval],
volumes[vol_index][x_min],
volumes[vol_index][y_min],
volumes[vol_index][z_min],
volumes[vol_index][x_max],
volumes[vol_index][y_max],
volumes[vol_index][y_max]);
StrCat(buffer, sizeof(buffer), line);
}
}
ReplyToCommand(client, buffer);
}
UpdatePlayerLocations()
{
new client;
for (client = 1; client <= maxclients; client++)
{
if (IsClientConnected(client) && IsClientInGame(client))
{
GetClientAbsOrigin(client, player_loc[client]);
}
}
}
HurtPlayersInVolume(volume_index)
{
new client;
new client_health;
decl String:client_name[64];
decl String:buffer[192];
new anticamp_echo = GetConVarBool(gCvars[CVAR_ANTICAMP_ECHO]);
for (client = 1; client <= maxclients; client++)
{
if (IsClientConnected(client) &&
IsClientInGame(client) &&
IsPlayerAlive(client) &&
IsPlayerHuman(client))
{
if (IsPlayerInVolume(client, volume_index))
{
ZR_PrintToChat(client, "Unfair camping");
client_health = GetClientHealth(client) - volumes[volume_index][volume_damage];
if (client_health > 0)
{
SetEntityHealth(client, client_health);
}
else
{
ForcePlayerSuicide(client);
GetClientName(client, client_name, sizeof(client_name));
SetGlobalTransTarget(client);
Format(buffer, sizeof(buffer), "%T", "Unfair camper slayed", LANG_SERVER, client_name, volume_index);
LogAction(client, client, buffer);
if (anticamp_echo)
{
FormatTextString(buffer, sizeof(buffer));
ZR_PrintToAdminChat(buffer);
}
}
}
}
}
}
bool:IsPlayerInVolume(client, volume_index)
{
new Float:player_loc_x = player_loc[client][0];
new Float:player_loc_y = player_loc[client][1];
new Float:player_loc_z = player_loc[client][2];
new debug_flags = GetConVarInt(gCvars[CVAR_DEBUG]);
if ((player_loc_x >= volumes[volume_index][x_min]) && (player_loc_x <= volumes[volume_index][x_max]))
{
if (debug_flags & 4) PrintToChatAll("[ZR] Debug, Anticamp -- IsPlayerInVolume: Client %d matches X values.", client);
if ((player_loc_y >= volumes[volume_index][y_min]) && (player_loc_y <= volumes[volume_index][y_max]))
{
if (debug_flags & 4) PrintToChatAll("[ZR] Debug, Anticamp -- IsPlayerInVolume: Client %d matches Y values.", client);
if ((player_loc_z >= volumes[volume_index][z_min]) && (player_loc_z <= volumes[volume_index][z_max]))
{
if (debug_flags & 4) PrintToChatAll("[ZR] Debug, Anticamp -- IsPlayerInVolume: Client %d matches Z values.", client);
return true;
}
}
}
return false;
}
GetFreeVolumeIndex()
{
for(new vol_index = 0; vol_index < MAX_VOLUMES; vol_index++)
{
if (!volumes[vol_index][volume_in_use])
{
return vol_index;
}
}
return -1;
}
bool:IsValidVolume(vol_index)
{
if (vol_index >= 0 && vol_index < MAX_VOLUMES)
{
return true;
}
else
{
return false;
}
}
ResetVolumes()
{
for (new vol_index = 0; vol_index < MAX_VOLUMES; vol_index++)
{
volumes[vol_index][volume_in_use] = false;
if (volumes[vol_index][volume_timer] != INVALID_HANDLE)
{
KillTimer(volumes[vol_index][volume_timer]);
volumes[vol_index][volume_timer] = INVALID_HANDLE;
}
}
}
public Action:Event_UpdatePlayerLocations(Handle:Timer)
{
UpdatePlayerLocations();
}
public Action:Event_HurtPlayers(Handle:Timer, any:volume_index)
{
HurtPlayersInVolume(volume_index);
}

View File

@ -25,6 +25,10 @@ CreateCommands()
RegAdminCmd("zr_admin", Command_AdminMenu, ADMFLAG_GENERIC, "Displays the admin menu for Zombie: Reloaded."); RegAdminCmd("zr_admin", Command_AdminMenu, ADMFLAG_GENERIC, "Displays the admin menu for Zombie: Reloaded.");
RegAdminCmd("zr_knockback_m", Command_KnockbackMMenu, ADMFLAG_GENERIC, "Displays the knockback multiplier menu."); RegAdminCmd("zr_knockback_m", Command_KnockbackMMenu, ADMFLAG_GENERIC, "Displays the knockback multiplier menu.");
RegAdminCmd("zr_teleadmin", Command_TeleMenu, ADMFLAG_GENERIC, "Displays the teleport admin menu for Zombie: Reloaded."); RegAdminCmd("zr_teleadmin", Command_TeleMenu, ADMFLAG_GENERIC, "Displays the teleport admin menu for Zombie: Reloaded.");
RegAdminCmd("zr_anticamp_create_volume", Command_AnticampCreateVolume, ADMFLAG_GENERIC, "Creates a rectangular hurt volume between two points. Usage: ht_create_volume <damage> <interval> <x1> <y1> <z1> <x2> <y2> <z2>");
RegAdminCmd("zr_anticamp_remove_volume", Command_AnticampRemoveVolume, ADMFLAG_GENERIC, "Removes a volume. Use zr_anticamp_list to list volumes. Usage: zr_anticamp_remove_volume <volume index>");
RegAdminCmd("zr_anticamp_list", Command_AnticampList, ADMFLAG_GENERIC, "List current volumes.");
} }
public Action:Command_Infect(client, argc) public Action:Command_Infect(client, argc)

View File

@ -81,7 +81,10 @@ enum ZRSettings
Handle:CVAR_INFECT_SHAKE_AMP, Handle:CVAR_INFECT_SHAKE_AMP,
Handle:CVAR_INFECT_SHAKE_FREQUENCY, Handle:CVAR_INFECT_SHAKE_FREQUENCY,
Handle:CVAR_INFECT_SHAKE_DURATION, Handle:CVAR_INFECT_SHAKE_DURATION,
Handle:CVAR_INFECT_ANTISTICK_FORCE Handle:CVAR_INFECT_ANTISTICK_FORCE,
Handle:CVAR_ANTICAMP,
Handle:CVAR_ANTICAMP_UPDATE_INTERVAL,
Handle:CVAR_ANTICAMP_ECHO
} }
new gCvars[ZRSettings]; new gCvars[ZRSettings];
@ -162,8 +165,13 @@ CreateCvars()
gCvars[CVAR_INFECT_SHAKE_FREQUENCY] = CreateConVar("zr_infect_shake_frequency", "1.0", "Frequency of the shake, when zr_infect_shake is 1"); gCvars[CVAR_INFECT_SHAKE_FREQUENCY] = CreateConVar("zr_infect_shake_frequency", "1.0", "Frequency of the shake, when zr_infect_shake is 1");
gCvars[CVAR_INFECT_SHAKE_DURATION] = CreateConVar("zr_infect_shake_duration", "5.0", "Duration of the shake, when zr_infect_shake is 1"); gCvars[CVAR_INFECT_SHAKE_DURATION] = CreateConVar("zr_infect_shake_duration", "5.0", "Duration of the shake, when zr_infect_shake is 1");
gCvars[CVAR_INFECT_ANTISTICK_FORCE] = CreateConVar("zr_infect_antistick_force", "-160.0", "Force to push away players from eachother on infection. Negative values push away, positive values pull. (0: Disable)"); gCvars[CVAR_INFECT_ANTISTICK_FORCE] = CreateConVar("zr_infect_antistick_force", "-160.0", "Force to push away players from eachother on infection. Negative values push away, positive values pull. (0: Disable)");
gCvars[CVAR_ANTICAMP] = CreateConVar("zr_anticamp", "1", "Enables or disables hurt volumes for preventing unfair camping. (0: Disable)");
gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL] = CreateConVar("zr_anticamp_update_interval", "1", "How often to update player locations (in seconds).");
gCvars[CVAR_ANTICAMP_ECHO] = CreateConVar("zr_anticamp_echo", "1", "Log kills done by anticamp to admin chat.");
HookConVarChange(gCvars[CVAR_ENABLE], EnableHook); HookConVarChange(gCvars[CVAR_ENABLE], EnableHook);
HookConVarChange(gCvars[CVAR_ANTICAMP], AnticampHook);
HookConVarChange(gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL], UpdateIntervalHook);
AutoExecConfig(true, "zombiereloaded", "sourcemod/zombiereloaded"); AutoExecConfig(true, "zombiereloaded", "sourcemod/zombiereloaded");
} }