d666fbf7ce
Finished base event handler for volfeatures. Finished zr_voladd, zr_vol_remove, zr_vol_list and zr_vol_dumpstates console commands. Removed unused function call in class module. Fixed minior bugs in parameter parser (paramtools.inc). Made a debug tools module with console commands for directly testing certain functions.
831 lines
22 KiB
SourcePawn
831 lines
22 KiB
SourcePawn
/*
|
|
* ============================================================================
|
|
*
|
|
* Zombie:Reloaded
|
|
*
|
|
* File: volfeatures.inc
|
|
* Type: Module
|
|
* Description: Provides functions for managing volumetric features.
|
|
*
|
|
* Copyright (C) 2009 Greyscale, Richard Helgeby
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* ============================================================================
|
|
*/
|
|
|
|
/**
|
|
* Total volumes that can be created in a map.
|
|
*/
|
|
#define ZR_VOLUMES_MAX 64
|
|
|
|
/**
|
|
* Represent a rectangular volume.
|
|
*/
|
|
enum VolumeAttributes
|
|
{
|
|
/* General */
|
|
bool:Vol_Enabled, /** Volume state. */
|
|
bool:Vol_InUse, /** Marks if the volume is used. */
|
|
|
|
/* Location */
|
|
Float:Vol_xMin, /** Minimum x position. */
|
|
Float:Vol_xMax, /** Maximum x position. */
|
|
|
|
Float:Vol_yMin, /** Minimum y position. */
|
|
Float:Vol_yMax, /** Maximum y position. */
|
|
|
|
Float:Vol_zMin, /** Minimum z position. */
|
|
Float:Vol_zMax, /** Maximum z position. */
|
|
|
|
/* Style */
|
|
VolumeEffects:Vol_Effect, /** Visual effect to apply on the volume. */
|
|
Vol_EffectColor[3], /** Render color of the effect. RGB colors. */
|
|
|
|
/* Data */
|
|
VolumeFeatureTypes:Vol_Type, /** The volumetric feature type. */
|
|
Vol_DataIndex, /** Index in remote feature array. */
|
|
|
|
/* Behaviour */
|
|
VolumeTeamFilters:Vol_TeamFilter, /** Team filtering. Trigger by certain teams, or all. */
|
|
Float:Vol_TriggerDelay /** Trigger delay. How many seconds players have to stay to trigger volume events. */
|
|
}
|
|
|
|
/**
|
|
* Available volumetric feature types.
|
|
*/
|
|
enum VolumeFeatureTypes
|
|
{
|
|
VolFeature_Invalid = 0,
|
|
VolFeature_Anticamp,
|
|
VolFeature_Knockback
|
|
}
|
|
|
|
/**
|
|
* Effects that can be applied on a volume. (Currently no effects.)
|
|
*/
|
|
enum VolumeEffects
|
|
{
|
|
VolEffect_None = 0,
|
|
VolEffect_Wireframe,
|
|
VolEffect_Smoke
|
|
}
|
|
|
|
/**
|
|
* Available team filter settings.
|
|
*/
|
|
enum VolumeTeamFilters
|
|
{
|
|
VolTeam_All = 0,
|
|
VolTeam_Humans,
|
|
VolTeam_Zombies
|
|
}
|
|
|
|
/**
|
|
* Volumes.
|
|
*/
|
|
new Volumes[ZR_VOLUMES_MAX][VolumeAttributes];
|
|
|
|
/**
|
|
* Total number of volumes.
|
|
*/
|
|
new VolumeCount;
|
|
|
|
/**
|
|
* List of player locations. Updated by a timer.
|
|
*/
|
|
new Float:VolPlayerLoc[MAXPLAYERS + 1][3];
|
|
|
|
/**
|
|
* Cache that specifies if a player is in a volume or not.
|
|
*/
|
|
new bool:VolPlayerInVolume[MAXPLAYERS + 1][ZR_VOLUMES_MAX];
|
|
|
|
/**
|
|
* Specifies whether the volumetric features module is enabled or not. Synced
|
|
* with zr_vol CVAR.
|
|
*/
|
|
new bool:VolEnabled;
|
|
|
|
/**
|
|
* Counter for trigger delay.
|
|
*/
|
|
new Float:VolPlayerCountDown[MAXPLAYERS + 1][ZR_VOLUMES_MAX];
|
|
|
|
/**
|
|
* The handle for a timer that updates player locations. This is the main timer
|
|
* and any feature events can't be updated faster than this interval.
|
|
*
|
|
* Note: Some features may have its own timer for actions on players.
|
|
*/
|
|
new Handle:hVolUpdateTimer;
|
|
|
|
/**
|
|
* The handle for a timer that do count down on trigger delays.
|
|
*/
|
|
new Handle:hVolTriggerTimer;
|
|
|
|
/**
|
|
* Cached interval value for trigger timer.
|
|
*/
|
|
new Float:VolTriggerInterval;
|
|
|
|
#include "zr/volfeatures/volevents"
|
|
#include "zr/volfeatures/volgenericattributes"
|
|
#include "zr/volfeatures/volcommands"
|
|
|
|
// Sub features.
|
|
#include "zr/volfeatures/volanticamp"
|
|
|
|
|
|
/**
|
|
* Initialize volumetric features.
|
|
*/
|
|
VolLoad()
|
|
{
|
|
// Cache CVAR value.
|
|
VolEnabled = GetConVarBool(g_hCvarsList[CVAR_VOL]);
|
|
|
|
// Initialize sub features.
|
|
VolAnticampInit();
|
|
}
|
|
|
|
/**
|
|
* Function alias for fully stopping volumetric features.
|
|
*/
|
|
VolDisable()
|
|
{
|
|
VolEnabled = false;
|
|
VolStopUpdateTimer();
|
|
VolDisableVolumes();
|
|
|
|
LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Disabled", "Volfeatures disabled.");
|
|
}
|
|
|
|
/**
|
|
* Function alias for starting volumetric features.
|
|
*/
|
|
VolEnable()
|
|
{
|
|
VolEnabled = true;
|
|
VolStartUpdateTimer();
|
|
VolEnableVolumes();
|
|
|
|
LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Enabled", "Volfeatures enabled.");
|
|
}
|
|
|
|
/**
|
|
* Disables all enabled volumes.
|
|
*/
|
|
VolDisableVolumes()
|
|
{
|
|
// Trigger disable event on all enabled volumes in use.
|
|
for (new volindex = 0; volindex < ZR_VOLUMES_MAX; volindex++)
|
|
{
|
|
if (Volumes[volindex][Vol_InUse] && Volumes[volindex][Vol_Enabled])
|
|
{
|
|
VolOnDisabled(volindex);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enables all disabled volumes.
|
|
*/
|
|
VolEnableVolumes()
|
|
{
|
|
// Trigger enable event on all volumes in use.
|
|
for (new volindex = 0; volindex < ZR_VOLUMES_MAX; volindex++)
|
|
{
|
|
if (Volumes[volindex][Vol_InUse] && !Volumes[volindex][Vol_Enabled])
|
|
{
|
|
VolOnEnabled(volindex);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts the update timer.
|
|
*
|
|
* @return True if timer is started, false otherwise.
|
|
*/
|
|
bool:VolStartUpdateTimer()
|
|
{
|
|
// Check if volumetric features is enabled.
|
|
if (!VolEnabled)
|
|
{
|
|
// Volumetric features disabled.
|
|
return false;
|
|
}
|
|
|
|
// Stop timer if it exist.
|
|
VolStopUpdateTimer();
|
|
|
|
// Get update interval.
|
|
new Float:interval = GetConVarFloat(g_hCvarsList[CVAR_VOL_UPDATE_INTERVAL]);
|
|
|
|
// Validate interval.
|
|
if (interval > 0.0)
|
|
{
|
|
// Create a new timer.
|
|
hVolUpdateTimer = CreateTimer(interval, Event_VolUpdateTimer, _, TIMER_REPEAT);
|
|
|
|
// Also start the trigger delay timer.
|
|
VolStartTriggerTimer();
|
|
|
|
// Volumetric features started.
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Volumetric features disabled.
|
|
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Volfeatures, "Config Validation", "Warning: Console variable \"zr_vol_update_interval\" is set to zero or negative. Must be positive.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Kills the update timer if it exists.
|
|
*/
|
|
VolStopUpdateTimer()
|
|
{
|
|
// Kill the timer if it's running.
|
|
if (hVolUpdateTimer != INVALID_HANDLE)
|
|
{
|
|
KillTimer(hVolUpdateTimer);
|
|
hVolUpdateTimer = INVALID_HANDLE;
|
|
}
|
|
|
|
// Also stop trigger delay timer.
|
|
VolStopTriggerTimer();
|
|
|
|
// Reset all trigger delay counters.
|
|
VolResetCountDown();
|
|
}
|
|
|
|
/**
|
|
* Starts the update timer if it exists.
|
|
*
|
|
* @return True if timer is started, false otherwise.
|
|
*/
|
|
bool:VolStartTriggerTimer()
|
|
{
|
|
// Make sure existing timer is killed.
|
|
VolStopTriggerTimer();
|
|
|
|
// Get trigger interval and cache it.
|
|
VolTriggerInterval = GetConVarFloat(g_hCvarsList[CVAR_VOL_TRIGGER_INTERVAL]);
|
|
|
|
// Validate interval.
|
|
if (VolTriggerInterval > 0.0)
|
|
{
|
|
// Start the timer.
|
|
hVolTriggerTimer = CreateTimer(VolTriggerInterval, Event_VolTriggerTimer, _, TIMER_REPEAT);
|
|
|
|
// Trigger timer started.
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Trigger timer not running. Either disabled or invalid interval.
|
|
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Volfeatures, "Config Validation", "Warning: Console variable \"zr_vol_trigger_interval\" is set to zero or negative. Must be positive.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Kills the trigger delay timer if it exists.
|
|
*/
|
|
VolStopTriggerTimer()
|
|
{
|
|
// Kill the timer if it's running.
|
|
if (hVolTriggerTimer != INVALID_HANDLE)
|
|
{
|
|
KillTimer(hVolTriggerTimer);
|
|
hVolTriggerTimer = INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets volume trigger delay counters on one or more players.
|
|
*
|
|
* @param client Optional. Specifies a single player to reset. Default is
|
|
* -1, all players.
|
|
*/
|
|
VolResetCountDown(client = -1)
|
|
{
|
|
// Check if a client is specified.
|
|
if (client > -1)
|
|
{
|
|
// Reset volume counters.
|
|
for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++)
|
|
{
|
|
VolPlayerCountDown[client][volumeIndex] = -1.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Reset all volume counters.
|
|
for (new clientIndex = 0; clientIndex < MAXPLAYERS + 1; clientIndex++)
|
|
{
|
|
for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++)
|
|
{
|
|
VolPlayerCountDown[clientIndex][volumeIndex] = -1.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates all player locations. Used for initialization.
|
|
*
|
|
* Note: If a client is specified, it's NOT validated. This function assumes
|
|
* the specified client is in game and alive.
|
|
*
|
|
* @param client Optional. Specify single client to be updated. Default is
|
|
* -1.
|
|
*/
|
|
VolUpdatePlayerLocation(client = -1)
|
|
{
|
|
if (client > 0)
|
|
{
|
|
// Assume the client is valid and save location in array.
|
|
GetClientAbsOrigin(client, VolPlayerLoc[client]);
|
|
}
|
|
else
|
|
{
|
|
for (client = 1; client <= MaxClients; client++)
|
|
{
|
|
// Check if client is in game and alive.
|
|
if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Save location in array.
|
|
GetClientAbsOrigin(client, VolPlayerLoc[client]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates player locations and trigger events for each player that enter or
|
|
* leave a volume.
|
|
*/
|
|
VolUpdatePlayerChanges()
|
|
{
|
|
new bool:volumeStates[ZR_VOLUMES_MAX];
|
|
new bool:volumeNewStates[ZR_VOLUMES_MAX];
|
|
|
|
new bool:newState;
|
|
new bool:oldState;
|
|
|
|
new Float:trigger_delay;
|
|
|
|
// Loop through all players.
|
|
for (new client = 1; client <= MaxClients; client++)
|
|
{
|
|
// Check if client is in game and alive.
|
|
if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
|
|
{
|
|
// Skip client.
|
|
continue;
|
|
}
|
|
|
|
// Get the current volume states based on player location cache.
|
|
VolGetPlayerStates(client, volumeStates, sizeof(volumeStates));
|
|
|
|
// Update player location cache.
|
|
GetClientAbsOrigin(client, VolPlayerLoc[client]);
|
|
|
|
// Get new volume states.
|
|
VolGetPlayerStates(client, volumeNewStates, sizeof(volumeNewStates));
|
|
|
|
// Loop through each volume and compare states.
|
|
for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++)
|
|
{
|
|
// Check if the volume is disabled and unused.
|
|
if (!VolInUse(volumeIndex) || !VolIsEnabled(volumeIndex))
|
|
{
|
|
// Skip volume.
|
|
continue;
|
|
}
|
|
|
|
// Check team filtering on the volume.
|
|
if (!VolTeamFilterMatch(client, volumeIndex))
|
|
{
|
|
// Team filter mismatch.
|
|
continue;
|
|
}
|
|
|
|
newState = volumeNewStates[volumeIndex];
|
|
oldState = volumeStates[volumeIndex];
|
|
|
|
// Check for no change.
|
|
if (newState == oldState)
|
|
{
|
|
// No change. Skip to next volume.
|
|
continue;
|
|
}
|
|
|
|
// Check if client entered the volume.
|
|
if (newState && !oldState)
|
|
{
|
|
// Get trigger delay value.
|
|
trigger_delay = Volumes[volumeIndex][Vol_TriggerDelay];
|
|
|
|
// Check if the volume has a trigger delay.
|
|
if (trigger_delay > 0.0)
|
|
{
|
|
// Set count down value.
|
|
VolPlayerCountDown[client][volumeIndex] = trigger_delay;
|
|
}
|
|
else
|
|
{
|
|
// Update cache.
|
|
VolPlayerInVolume[client][volumeIndex] = true;
|
|
|
|
// No trigger delay, trigger event instantly.
|
|
VolOnPlayerEnter(client, volumeIndex);
|
|
}
|
|
}
|
|
|
|
// Check if client left the volume.
|
|
else if (!newState && oldState)
|
|
{
|
|
// Make sure count down value is reset.
|
|
VolPlayerCountDown[client][volumeIndex] = -1.0;
|
|
|
|
// Update cache.
|
|
VolPlayerInVolume[client][volumeIndex] = false;
|
|
|
|
// Trigger event.
|
|
VolOnPlayerLeave(client, volumeIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns wether a point is within a certain location.
|
|
*
|
|
* @param point The point to check.
|
|
* @param min Minimum x, y and z values of the location.
|
|
* @param max Maximum x, y and z values of the location.
|
|
* @return True if the position is within min and max values. False
|
|
* otherwise.
|
|
*/
|
|
bool:IsPointInLocation(Float:point[3], Float:min[3], Float:max[3])
|
|
{
|
|
// Cache to avoid re-indexing arrays.
|
|
new Float:posX = point[0];
|
|
new Float:posY = point[1];
|
|
new Float:posZ = point[2];
|
|
|
|
// Check if within x boundaries.
|
|
if ((posX >= min[0]) && (posX <= max[0]))
|
|
{
|
|
// Check if within y boundaries.
|
|
if ((posY >= min[1]) && (posY <= max[1]))
|
|
{
|
|
// Check if within x boundaries.
|
|
if ((posZ >= min[2]) && (posZ <= max[2]))
|
|
{
|
|
// The point is within the location boundaries.
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// The point is outside the location boundaries.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns wether a volume is marked as in use.
|
|
*
|
|
* Note: Does not validate index.
|
|
*
|
|
* @param volumeIndex The volume index.
|
|
* @return True if in use, false otherwise.
|
|
*/
|
|
bool:VolInUse(volumeIndex)
|
|
{
|
|
return Volumes[volumeIndex][Vol_InUse];
|
|
}
|
|
|
|
/**
|
|
* Returns wether a volume is enabled or not.
|
|
*
|
|
* Note: Does not validate index.
|
|
*
|
|
* @param volumeIndex The volume index.
|
|
* @return True if enabled, false otherwise.
|
|
*/
|
|
bool:VolIsEnabled(volumeIndex)
|
|
{
|
|
return Volumes[volumeIndex][Vol_Enabled];
|
|
}
|
|
|
|
/**
|
|
* Validates a volume index.
|
|
*
|
|
* @param volumeIndex The volume index.
|
|
* @return True if valid, false otherwise.
|
|
*/
|
|
bool:VolIsValidIndex(volumeIndex)
|
|
{
|
|
if (volumeIndex >= 0 && volumeIndex < ZR_VOLUMES_MAX)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the first free volume index.
|
|
*
|
|
* @return The first free volume index if successful, or -1 if there are
|
|
* no free volumes.
|
|
*/
|
|
VolGetFreeVolume()
|
|
{
|
|
// Loop through all volumes.
|
|
for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++)
|
|
{
|
|
// Check if it's free.
|
|
if (!VolInUse(volumeIndex))
|
|
{
|
|
return volumeIndex;
|
|
}
|
|
}
|
|
|
|
// No free volumes found.
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Gets a free index in the data array for the specified volume type.
|
|
*
|
|
* @param volumeType Volumetric feature type.
|
|
* @return Data index, or -1 on error.
|
|
*/
|
|
VolGetFreeDataIndex(VolumeFeatureTypes:volumeType)
|
|
{
|
|
switch (volumeType)
|
|
{
|
|
case VolFeature_Anticamp:
|
|
{
|
|
return VolAnticampGetFreeIndex();
|
|
}
|
|
case VolFeature_Knockback:
|
|
{
|
|
// TOTO: Finish incomplete feature.
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// No match.
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Checks if the specified client match the team filtering for the specified
|
|
* volume.
|
|
*
|
|
* @param client The client index.
|
|
* @param volumeIndex The volume to check team filtering on.
|
|
* @return True if client pass the team filtering, false otherwise.
|
|
*/
|
|
bool:VolTeamFilterMatch(client, volumeIndex)
|
|
{
|
|
new VolumeTeamFilters:filter;
|
|
|
|
// Chache filter value.
|
|
filter = Volumes[volumeIndex][Vol_TeamFilter];
|
|
|
|
switch (filter)
|
|
{
|
|
case VolTeam_All:
|
|
{
|
|
// All maches everyone.
|
|
return true;
|
|
}
|
|
case VolTeam_Humans:
|
|
{
|
|
// Check if client is a human.
|
|
return InfectIsClientHuman(client);
|
|
}
|
|
case VolTeam_Zombies:
|
|
{
|
|
// Check if client is a zombie.
|
|
return InfectIsClientInfected(client);
|
|
}
|
|
}
|
|
|
|
// Invalid filter value.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gets wether a client is within volumes or not. Result is stored in a boolean
|
|
* array.
|
|
*
|
|
* @param client The client index.
|
|
* @param buffer Destination buffer.
|
|
* @param maxlen Size of destination buffer.
|
|
* @return Number of volumes the client is within.
|
|
*/
|
|
VolGetPlayerStates(client, bool:buffer[], maxlen)
|
|
{
|
|
new volumeBuffer[VolumeAttributes];
|
|
new volCount;
|
|
|
|
new Float:volMinBuffer[3];
|
|
new Float:volMaxBuffer[3];
|
|
|
|
// Loop through all available volumes.
|
|
for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX && volumeIndex < maxlen; volumeIndex++)
|
|
{
|
|
if (VolInUse(volumeIndex))
|
|
{
|
|
// Chache volume to avoid re-indexing.
|
|
volumeBuffer = Volumes[volumeIndex];
|
|
|
|
// Get min positions.
|
|
volMinBuffer[0] = volumeBuffer[Vol_xMin];
|
|
volMinBuffer[1] = volumeBuffer[Vol_yMin];
|
|
volMinBuffer[2] = volumeBuffer[Vol_zMin];
|
|
|
|
// Get max positions.
|
|
volMaxBuffer[0] = volumeBuffer[Vol_xMax];
|
|
volMaxBuffer[1] = volumeBuffer[Vol_yMax];
|
|
volMaxBuffer[2] = volumeBuffer[Vol_zMax];
|
|
|
|
// Check the cached player location.
|
|
if (IsPointInLocation(VolPlayerLoc[client], volMinBuffer, volMaxBuffer))
|
|
{
|
|
// Mark player as in volume.
|
|
buffer[volumeIndex] = true;
|
|
volCount++;
|
|
}
|
|
else
|
|
{
|
|
// Do explicit reset.
|
|
buffer[volumeIndex] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return volCount;
|
|
}
|
|
|
|
/**
|
|
* Converts a string into a volumetric feature type.
|
|
*
|
|
* @param volType String to convert. Name of type.
|
|
* @return Volumetric feature type or VolFeature_Invalid on error.
|
|
*/
|
|
VolumeFeatureTypes:VolGetTypeFromString(const String:volType[])
|
|
{
|
|
// Check if empty.
|
|
if (strlen(volType) == 0)
|
|
{
|
|
return VolFeature_Invalid;
|
|
}
|
|
|
|
// Match types.
|
|
if (StrEqual(volType, "anticamp", false))
|
|
{
|
|
return VolFeature_Anticamp;
|
|
}
|
|
else if (StrEqual(volType, "knockback", false))
|
|
{
|
|
return VolFeature_Knockback;
|
|
}
|
|
|
|
// No match.
|
|
return VolFeature_Invalid;
|
|
}
|
|
|
|
/**
|
|
* Converts a volume type to a string.
|
|
*
|
|
* @param volType Volume type to convert.
|
|
* @param buffer Destination string buffer.
|
|
* @param maxlen Size of destination buffer.
|
|
* @param shortName Optional. Write short name or human readable name.
|
|
* Default is human readable (false).
|
|
* @return Number of cells written.
|
|
*/
|
|
VolTypeToString(VolumeFeatureTypes:volType, String:buffer[], maxlen, bool:shortName = false)
|
|
{
|
|
switch (volType)
|
|
{
|
|
case VolFeature_Invalid:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "") : strcopy(buffer, maxlen, "(none)");
|
|
}
|
|
case VolFeature_Anticamp:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "anticamp") : strcopy(buffer, maxlen, "Anti camp");
|
|
}
|
|
case VolFeature_Knockback:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "knockback") : strcopy(buffer, maxlen, "Knock back modifier");
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Callback for update timer. This is the main timer in volumetric features.
|
|
*/
|
|
public Action:Event_VolUpdateTimer(Handle:timer)
|
|
{
|
|
VolUpdatePlayerChanges();
|
|
}
|
|
|
|
/**
|
|
* Callback for trigger delay timer.
|
|
*/
|
|
public Action:Event_VolTriggerTimer(Handle:timer)
|
|
{
|
|
new Float:countDown;
|
|
|
|
// Loop through all players.
|
|
for (new client = 1; client <= MaxClients; client++)
|
|
{
|
|
// Loop through all volumes.
|
|
for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++)
|
|
{
|
|
// Check if volume is in use and enabled.
|
|
if (!VolInUse(volumeIndex) || !VolIsEnabled(volumeIndex))
|
|
{
|
|
// Not in use or enabled, skip volume.
|
|
continue;
|
|
}
|
|
|
|
// Get count down value.
|
|
countDown = VolPlayerCountDown[client][volumeIndex];
|
|
|
|
// Check if volume trigger delay is enabled.
|
|
if (countDown > 0.0)
|
|
{
|
|
// Substract by trigger interval.
|
|
countDown -= VolTriggerInterval;
|
|
|
|
// Check if time is up.
|
|
if (countDown <= 0.0)
|
|
{
|
|
// Update cache.
|
|
VolPlayerInVolume[client][volumeIndex] = true;
|
|
|
|
// Trigger volume enter event.
|
|
VolOnPlayerEnter(client, volumeIndex);
|
|
|
|
// Reset count down value.
|
|
VolPlayerCountDown[client][volumeIndex] = -1.0;
|
|
}
|
|
|
|
// Update count down value and continue.
|
|
VolPlayerCountDown[client][volumeIndex] = countDown;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when zr_vol CVAR is changed.
|
|
*/
|
|
public VolEnabledChanged(Handle:cvar, const String:oldvalue[], const String:newvalue[])
|
|
{
|
|
new bool:isEnabled = bool:StringToInt(newvalue);
|
|
|
|
if (isEnabled)
|
|
{
|
|
// Volumetric features is enabled.
|
|
VolEnable();
|
|
}
|
|
else
|
|
{
|
|
// Volumetric features is disabled.
|
|
VolDisable();
|
|
}
|
|
}
|