Added flag on some timers so we are sure they are killed on map change. Added stop event on health regeneration timer when applying classes, if the class has no regeneration. Cvar zr_classes_default_admin is now replaced by admin-only classes. Old cvar is zr_classes_default_admin_mode.
929 lines
26 KiB
SourcePawn
929 lines
26 KiB
SourcePawn
/*
|
|
* ============================================================================
|
|
*
|
|
* Zombie:Reloaded
|
|
*
|
|
* File: volanticamp.inc
|
|
* Type: Module
|
|
* Description: Anti-camp handler.
|
|
*
|
|
* 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/>.
|
|
*
|
|
* ============================================================================
|
|
*/
|
|
|
|
/**
|
|
* Actions to do with players in anti-camp volumes.
|
|
*/
|
|
enum VolAnticampAction
|
|
{
|
|
Anticamp_NoAction, /** Do nothing but give a warning. */
|
|
Anticamp_Damage, /** Give damage to player. */
|
|
Anticamp_Slay, /** Slay player. */
|
|
Anticamp_Drug, /** Drug player. */
|
|
Anticamp_Ignite /** Ignite player. */
|
|
}
|
|
|
|
/**
|
|
* Warning types.
|
|
*/
|
|
enum VolAnticampeWarningType
|
|
{
|
|
Anticamp_NoWarning, /** No warning messages. */
|
|
Anticamp_Chat, /** Print warning in chat area. */
|
|
Anticamp_Center, /** Print centered warning message. */
|
|
Anticamp_Menu /** Print a menu-like warning message with close option. */
|
|
}
|
|
|
|
/**
|
|
* Data structure for a anti-camp volume.
|
|
*/
|
|
enum VolTypeAnticamp
|
|
{
|
|
bool:Anticamp_InUse, /** Specifies if the data index is used or not. */
|
|
Float:Anticamp_Interval, /** How often to trigger an action. */
|
|
Handle:Anticamp_Timer, /** Action timer handle. */
|
|
|
|
VolAnticampAction:Anticamp_Action, /** What to do with players in anti-camp volumes */
|
|
Float:Anticamp_Amount, /** Amount depending on action type. Usually time in seconds or damage amount. */
|
|
|
|
VolAnticampeWarningType:Anticamp_Warning, /** How to warn the player. */
|
|
String:Anticamp_Message[256] /** Override warning message. Max 256 characters. */
|
|
}
|
|
|
|
/**
|
|
* Anti-camp data.
|
|
*/
|
|
new AnticampData[ZR_VOLUMES_MAX][VolTypeAnticamp];
|
|
|
|
/**
|
|
* Event callback. Enables a anticamp volume.
|
|
*
|
|
* @param volumeIndex The volume index.
|
|
*/
|
|
VolAnticampEnable(volumeIndex)
|
|
{
|
|
new Float:interval;
|
|
new Handle:timer;
|
|
|
|
// Validate index.
|
|
if (!VolIsValidIndex(volumeIndex))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Get data index.
|
|
new dataindex = Volumes[volumeIndex][Vol_DataIndex];
|
|
|
|
// Validate data index.
|
|
if (!VolAnticampValidateIndex(dataindex))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Check if in use.
|
|
if (AnticampData[dataindex][Anticamp_InUse])
|
|
{
|
|
// Kill timer if it exist.
|
|
timer = AnticampData[dataindex][Anticamp_Timer];
|
|
if (timer != INVALID_HANDLE)
|
|
{
|
|
KillTimer(timer);
|
|
AnticampData[dataindex][Anticamp_Timer] = INVALID_HANDLE;
|
|
}
|
|
|
|
// Get interval.
|
|
interval = AnticampData[dataindex][Anticamp_Interval];
|
|
|
|
// Validate interval.
|
|
if (interval > 0.0)
|
|
{
|
|
AnticampData[dataindex][Anticamp_Timer] = CreateTimer(interval, Event_VolAnticampTrigger, volumeIndex, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
|
LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Vol state", "Enabled anticamp volume %d.", volumeIndex);
|
|
}
|
|
else
|
|
{
|
|
LogEvent(_, LogType_Error, LOG_CORE_EVENTS, LogModule_Volfeatures, "Config Validation", "Warning: Invalid interval %.2f in anticamp volume %d.", interval, volumeIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts all existing anticamp timers.
|
|
*
|
|
* TODO: Reuse code! This is almost duplicate of VolAnticampEnable.
|
|
*/
|
|
stock VolAnticampEnableAll()
|
|
{
|
|
new Float:interval;
|
|
new dataindex;
|
|
|
|
// Loop through all volumes.
|
|
for (new volumeindex = 0; volumeindex < ZR_VOLUMES_MAX; volumeindex++)
|
|
{
|
|
// Check if unused.
|
|
if (!VolInUse(volumeindex))
|
|
{
|
|
// Volume not in use, skip it.
|
|
continue;
|
|
}
|
|
|
|
// Check if it's a anticamp volume.
|
|
if (VolIsType(volumeindex, VolFeature_Anticamp))
|
|
{
|
|
// Get data index.
|
|
dataindex = Volumes[volumeindex][Vol_DataIndex];
|
|
|
|
// Kill timer if it exist.
|
|
timer = AnticampData[dataindex][Anticamp_Timer];
|
|
if (timer != INVALID_HANDLE)
|
|
{
|
|
KillTimer(timer);
|
|
AnticampData[dataindex][Anticamp_Timer] = INVALID_HANDLE;
|
|
}
|
|
|
|
// Get interval.
|
|
interval = AnticampData[dataindex][Anticamp_Interval];
|
|
|
|
// Validate interval.
|
|
if (interval > 0.0)
|
|
{
|
|
AnticampData[dataindex][Anticamp_Timer] = CreateTimer(interval, Event_VolAnticampTrigger, volumeindex, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
|
LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Vol state", "Enabled anticamp volume %d.", volumeIndex);
|
|
}
|
|
else
|
|
{
|
|
LogEvent(_, LogType_Error, LOG_CORE_EVENTS, LogModule_Volfeatures, "Config Validation", "Warning: Invalid interval %.2f in anticamp volume %d.", interval, volumeIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Event callback. Stops existing anticamp timer on a volume.
|
|
*/
|
|
VolAnticampDisable(volumeIndex)
|
|
{
|
|
new Handle:timerbuffer;
|
|
|
|
// Validate index.
|
|
if (!VolIsValidIndex(volumeIndex))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Get data index.
|
|
new dataindex = Volumes[volumeIndex][Vol_DataIndex];
|
|
|
|
// Validate data index.
|
|
if (!VolAnticampValidateIndex(dataindex))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Check if in use.
|
|
if (AnticampData[dataindex][Anticamp_InUse])
|
|
{
|
|
// Stop timer.
|
|
timerbuffer = AnticampData[dataindex][Anticamp_Timer];
|
|
if (timerbuffer != INVALID_HANDLE)
|
|
{
|
|
KillTimer(timerbuffer);
|
|
AnticampData[dataindex][Anticamp_Timer] = INVALID_HANDLE;
|
|
}
|
|
|
|
LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Vol state", "Disabled anticamp volume %d.", volumeIndex);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Stops all existing anticamp timers.
|
|
*/
|
|
stock VolAnticampDisableAll()
|
|
{
|
|
new Handle:timerbuffer;
|
|
|
|
// Loop through all volumes.
|
|
for (new dataindex = 0; dataindex < ZR_VOLUMES_MAX; dataindex++)
|
|
{
|
|
// Check if in use.
|
|
if (AnticampData[dataindex][Anticamp_InUse])
|
|
{
|
|
// Stop timer.
|
|
timerbuffer = AnticampData[dataindex][Anticamp_Timer];
|
|
if (timerbuffer != INVALID_HANDLE)
|
|
{
|
|
KillTimer(timerbuffer);
|
|
AnticampData[dataindex][Anticamp_Timer] = INVALID_HANDLE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disables feature and resets data to defaults at the specified index.
|
|
*
|
|
* @param dataIndex Local data index.
|
|
*/
|
|
VolAnticampReset(dataIndex)
|
|
{
|
|
AnticampData[dataIndex][Anticamp_InUse] = false;
|
|
|
|
AnticampData[dataIndex][Anticamp_Interval] = 1.0;
|
|
if (AnticampData[dataIndex][Anticamp_Timer] != INVALID_HANDLE)
|
|
{
|
|
KillTimer(AnticampData[dataIndex][Anticamp_Timer]);
|
|
AnticampData[dataIndex][Anticamp_Timer] = INVALID_HANDLE;
|
|
}
|
|
|
|
AnticampData[dataIndex][Anticamp_Action] = Anticamp_Damage;
|
|
AnticampData[dataIndex][Anticamp_Amount] = 5.0;
|
|
|
|
AnticampData[dataIndex][Anticamp_Warning] = Anticamp_Chat;
|
|
Format(String:AnticampData[dataIndex][Anticamp_Message], 256, "");
|
|
}
|
|
|
|
/**
|
|
* Initialization event for anticamp feature.
|
|
*/
|
|
VolAnticampInit()
|
|
{
|
|
// Set default attributes.
|
|
for (new dataindex = 0; dataindex < ZR_VOLUMES_MAX; dataindex++)
|
|
{
|
|
VolAnticampReset(dataindex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when a player leave a anticamp volume.
|
|
*
|
|
* @param client The client index.
|
|
* @param volumeIndex Index of volume the player left.
|
|
*/
|
|
VolAnticampOnPlayerLeave(client, volumeIndex)
|
|
{
|
|
new dataindex = Volumes[volumeIndex][Vol_DataIndex];
|
|
|
|
switch (AnticampData[dataindex][Anticamp_Action])
|
|
{
|
|
case Anticamp_Drug:
|
|
{
|
|
// TODO: Un-drug player.
|
|
}
|
|
case Anticamp_Ignite:
|
|
{
|
|
ExtinguishEntity(client);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Timer callback for anticamp volumes. Applies actions on players in volumes.
|
|
*/
|
|
public Action:Event_VolAnticampTrigger(Handle:timer, any:volumeIndex)
|
|
{
|
|
// Loop through all players.
|
|
for (new client = 1; client <= MaxClients; client++)
|
|
{
|
|
// Validate client's connection state.
|
|
if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if the volume is unused.
|
|
if (!VolInUse(volumeIndex))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if the volume is disabled.
|
|
if (!VolIsEnabled(volumeIndex))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check if it's a anticamp volume.
|
|
if (VolIsType(volumeIndex, VolFeature_Anticamp))
|
|
{
|
|
// Check if player is in the volume.
|
|
if (VolPlayerInVolume[client][volumeIndex])
|
|
{
|
|
// Apply action.
|
|
VolAnticampApplyAction(client, Volumes[volumeIndex][Vol_DataIndex], volumeIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Applies action on a client for the specified volume.
|
|
*
|
|
* @param client The client index.
|
|
* @param dataIndex Local data index.
|
|
* @param volumeIndex The volume index.
|
|
*/
|
|
VolAnticampApplyAction(client, dataIndex, volumeIndex)
|
|
{
|
|
new Float:amount = AnticampData[dataIndex][Anticamp_Amount];
|
|
|
|
// Set client language.
|
|
SetGlobalTransTarget(client);
|
|
|
|
// Get player name.
|
|
decl String:name[64];
|
|
GetClientName(client, name, sizeof(name));
|
|
|
|
// Send warning message.
|
|
VolAnticampWarnPlayer(client, dataIndex);
|
|
|
|
switch (AnticampData[dataIndex][Anticamp_Action])
|
|
{
|
|
case Anticamp_NoAction:
|
|
{
|
|
// Do nothing.
|
|
}
|
|
case Anticamp_Damage:
|
|
{
|
|
// Give damage to player. Kill if zero HP or below.
|
|
new damage = RoundToNearest(amount);
|
|
new health = GetClientHealth(client) - damage;
|
|
|
|
if (health > 0)
|
|
{
|
|
SetEntityHealth(client, health);
|
|
}
|
|
else
|
|
{
|
|
// Health is zero or below. Kill player.
|
|
ForcePlayerSuicide(client);
|
|
|
|
// Log event.
|
|
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_Volfeatures, "Anti-camp", "%t", "Vol Slay", name, volumeIndex);
|
|
}
|
|
}
|
|
case Anticamp_Slay:
|
|
{
|
|
// Instantly kill the player.
|
|
ForcePlayerSuicide(client);
|
|
|
|
// Log event.
|
|
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_Volfeatures, "Anti-camp", "%t", "Vol Slay", name, volumeIndex);
|
|
}
|
|
case Anticamp_Drug:
|
|
{
|
|
// TODO: Trigger sm_drug on client some how.
|
|
}
|
|
case Anticamp_Ignite:
|
|
{
|
|
// Validate amount.
|
|
if (amount > 0.0)
|
|
{
|
|
// Extinguish player first.
|
|
ExtinguishEntity(client);
|
|
|
|
// Ignite player for "amount" seconds.
|
|
IgniteEntity(client, amount);
|
|
|
|
// Log event.
|
|
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_Volfeatures, "Anti-camp", "%t", "Vol Ignite", name, volumeIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gives a warning to the specified player for the specified volume.
|
|
*
|
|
* @param client The client index.
|
|
* @param dataIndex Local data index.
|
|
*/
|
|
VolAnticampWarnPlayer(client, dataIndex)
|
|
{
|
|
decl String:buffer[256];
|
|
new bool:custommessage = (strlen(AnticampData[dataIndex][Anticamp_Message]) > 0) ? true : false;
|
|
|
|
// Set language.
|
|
SetGlobalTransTarget(client);
|
|
|
|
// Format message.
|
|
if (custommessage)
|
|
{
|
|
// Use custom message.
|
|
strcopy(buffer, sizeof(buffer), AnticampData[dataIndex][Anticamp_Message]);
|
|
}
|
|
else
|
|
{
|
|
// Use default anticamp message in translations file.
|
|
Format(buffer, sizeof(buffer), "%t", "Vol Anticamp Message");
|
|
}
|
|
|
|
switch (AnticampData[dataIndex][Anticamp_Warning])
|
|
{
|
|
case Anticamp_NoWarning:
|
|
{
|
|
// Do nothing.
|
|
}
|
|
case Anticamp_Chat:
|
|
{
|
|
// Apply ZR formatting and print chat message.
|
|
TranslationPluginFormatString(buffer, sizeof(buffer));
|
|
PrintToChat(client, buffer);
|
|
}
|
|
case Anticamp_Center:
|
|
{
|
|
// Print centered message.
|
|
PrintCenterText(client, buffer);
|
|
}
|
|
case Anticamp_Menu:
|
|
{
|
|
// Display the message in a menu panel.
|
|
new Handle:panel = CreatePanel();
|
|
|
|
SetPanelTitle(panel, "Zombie:Reloaded");
|
|
DrawPanelItem(panel, "", ITEMDRAW_SPACER);
|
|
DrawPanelItem(panel, buffer);
|
|
DrawPanelItem(panel, "", ITEMDRAW_SPACER);
|
|
|
|
SetPanelCurrentKey(panel, 10);
|
|
|
|
Format(buffer, sizeof(buffer), "%t", "Exit");
|
|
DrawPanelItem(panel, buffer, ITEMDRAW_CONTROL);
|
|
|
|
SendPanelToClient(panel, client, Handler_AnitcampDummy, 10);
|
|
CloseHandle(panel);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dummy handler for panel messages.
|
|
*/
|
|
public Handler_AnitcampDummy(Handle:menu, MenuAction:action, param1, param2)
|
|
{
|
|
// Do nothing.
|
|
}
|
|
|
|
/**
|
|
* Gets the first free anticamp data index.
|
|
*
|
|
* @return The first free anticamp data index if successful, or -1 if
|
|
* there are no free volumes.
|
|
*/
|
|
VolAnticampGetFreeIndex()
|
|
{
|
|
// Loop through all indexes.
|
|
for (new dataindex = 0; dataindex < ZR_VOLUMES_MAX; dataindex++)
|
|
{
|
|
// Check if it's free.
|
|
if (!AnticampData[dataindex][Anticamp_InUse])
|
|
{
|
|
// Mark as in use.
|
|
AnticampData[dataindex][Anticamp_InUse] = true;
|
|
|
|
// Return the new index.
|
|
return dataindex;
|
|
}
|
|
}
|
|
|
|
// No free index found.
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Validates local data index.
|
|
*
|
|
* @param dataIndex Index to validate.
|
|
* @return True if valid, false otherwise.
|
|
*/
|
|
bool:VolAnticampValidateIndex(dataIndex)
|
|
{
|
|
if (dataIndex >= 0 && dataIndex < ZR_VOLUMES_MAX)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dumps data to be used by zr_vol_list command.
|
|
*
|
|
* @param dataIndex Index in anticamp data array.
|
|
* @param buffer Destination string buffer.
|
|
* @param maxlen Size of destination buffer.
|
|
* @return Number of cells written.
|
|
*/
|
|
VolAnticampDumpData(dataIndex, String:buffer[], maxlen)
|
|
{
|
|
decl String:linebuffer[128];
|
|
decl String:valuebuffer[256];
|
|
new anticampcache[VolTypeAnticamp];
|
|
new cellswritten;
|
|
|
|
// Validate index.
|
|
if (!VolAnticampValidateIndex(dataIndex))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Initialize and clear buffer.
|
|
buffer[0] = 0;
|
|
|
|
// Cache data.
|
|
anticampcache = AnticampData[dataIndex];
|
|
|
|
Format(linebuffer, sizeof(linebuffer), "Interval: %.2f\n", anticampcache[Anticamp_Interval]);
|
|
cellswritten += StrCat(buffer, maxlen, linebuffer);
|
|
|
|
VolAnticampActionToString(anticampcache[Anticamp_Action], valuebuffer, sizeof(valuebuffer));
|
|
Format(linebuffer, sizeof(linebuffer), "Action: %s\n", valuebuffer);
|
|
cellswritten += StrCat(buffer, maxlen, linebuffer);
|
|
|
|
Format(linebuffer, sizeof(linebuffer), "Action amount: %.2f\n", anticampcache[Anticamp_Amount]);
|
|
cellswritten += StrCat(buffer, maxlen, linebuffer);
|
|
|
|
VolAnticampWarningToString(anticampcache[Anticamp_Warning], valuebuffer, sizeof(valuebuffer));
|
|
Format(linebuffer, sizeof(linebuffer), "Warning type: %s\n", valuebuffer);
|
|
cellswritten += StrCat(buffer, maxlen, linebuffer);
|
|
|
|
strcopy(valuebuffer, sizeof(valuebuffer), anticampcache[Anticamp_Message]);
|
|
Format(linebuffer, sizeof(linebuffer), "Warning message: \"%s\"\n", valuebuffer);
|
|
cellswritten += StrCat(buffer, maxlen, linebuffer);
|
|
|
|
return cellswritten;
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* *
|
|
* CONVERTING FUNCTIONS *
|
|
* *
|
|
**************************************/
|
|
|
|
/**
|
|
* Converts a action type to a string.
|
|
*
|
|
* @param actionType Action 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.
|
|
*/
|
|
VolAnticampActionToString(VolAnticampAction:actionType, String:buffer[], maxlen, bool:shortName = false)
|
|
{
|
|
switch (actionType)
|
|
{
|
|
case Anticamp_NoAction:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "none") : strcopy(buffer, maxlen, "No action");
|
|
}
|
|
case Anticamp_Damage:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "damage") : strcopy(buffer, maxlen, "Damage player");
|
|
}
|
|
case Anticamp_Slay:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "slay") : strcopy(buffer, maxlen, "Kill player");
|
|
}
|
|
case Anticamp_Drug:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "drug") : strcopy(buffer, maxlen, "Drug player ");
|
|
}
|
|
case Anticamp_Ignite:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "ignite") : strcopy(buffer, maxlen, "Ignite player");
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Converts a action string type to a action type.
|
|
*
|
|
* @param action Action string type to convert.
|
|
* @return Action type or Anticamp_NoAction if failed.
|
|
*/
|
|
stock VolAnticampAction:VolAnticampStringToAction(const String:action[])
|
|
{
|
|
// Check if empty.
|
|
if (strlen(action) == 0)
|
|
{
|
|
return Anticamp_NoAction;
|
|
}
|
|
|
|
if (StrEqual(action, "none", false))
|
|
{
|
|
return Anticamp_NoWarning;
|
|
}
|
|
else if (StrEqual(action, "damage", false))
|
|
{
|
|
return Anticamp_Damage;
|
|
}
|
|
else if (StrEqual(action, "slay", false))
|
|
{
|
|
return Anticamp_Slay;
|
|
}
|
|
else if (StrEqual(action, "drug", false))
|
|
{
|
|
return Anticamp_Drug;
|
|
}
|
|
else if (StrEqual(action, "ignite", false))
|
|
{
|
|
return Anticamp_Ignite;
|
|
}
|
|
|
|
// No match.
|
|
return Anticamp_NoAction;
|
|
}
|
|
|
|
/**
|
|
* Converts a warning type to a string.
|
|
*
|
|
* @param warningType Warning 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.
|
|
*/
|
|
VolAnticampWarningToString(VolAnticampeWarningType:warningType, String:buffer[], maxlen, bool:shortName = false)
|
|
{
|
|
switch (warningType)
|
|
{
|
|
case Anticamp_NoWarning:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "none") : strcopy(buffer, maxlen, "No warning");
|
|
}
|
|
case Anticamp_Chat:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "chat") : strcopy(buffer, maxlen, "Chat area");
|
|
}
|
|
case Anticamp_Center:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "center") : strcopy(buffer, maxlen, "Centered message");
|
|
}
|
|
case Anticamp_Menu:
|
|
{
|
|
return shortName ? strcopy(buffer, maxlen, "menu") : strcopy(buffer, maxlen, "Message in menu panel");
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Converts a warning string type to a warning type.
|
|
*
|
|
* @param warning Warning string type to convert.
|
|
* @return Warning type, or Anticamp_NoWarning if failed.
|
|
*/
|
|
stock VolAnticampeWarningType:VolAnticampStringToWarning(const String:warning[])
|
|
{
|
|
// Check if empty.
|
|
if (strlen(warning) == 0)
|
|
{
|
|
return Anticamp_NoWarning;
|
|
}
|
|
|
|
if (StrEqual(warning, "none", false))
|
|
{
|
|
return Anticamp_NoWarning;
|
|
}
|
|
else if (StrEqual(warning, "chat", false))
|
|
{
|
|
return Anticamp_Chat;
|
|
}
|
|
else if (StrEqual(warning, "center", false))
|
|
{
|
|
return Anticamp_Center;
|
|
}
|
|
else if (StrEqual(warning, "menu", false))
|
|
{
|
|
return Anticamp_Menu;
|
|
}
|
|
|
|
// No match.
|
|
return Anticamp_NoWarning;
|
|
}
|
|
|
|
|
|
/**************************************
|
|
* *
|
|
* ATTRIBUTE FUNCTIONS *
|
|
* *
|
|
**************************************/
|
|
|
|
/**
|
|
* Sets anticamp spesific attributes on a anticamp volume.
|
|
*
|
|
* @param dataIndex Local data index.
|
|
* @param attribName Attribute to modify.
|
|
* @param attribVlue Attribute value to set.
|
|
* @return True if successfully set, false otherwise.
|
|
*/
|
|
bool:VolAnticampSetAttribute(dataIndex, const String:attribName[], const String:attribValue[])
|
|
{
|
|
// Validate data index.
|
|
if (!VolAnticampValidateIndex(dataIndex))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Check attribute names.
|
|
if (StrEqual(attribName, "interval", false))
|
|
{
|
|
if (VolAnticampSetIntervalString(dataIndex, attribValue))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if (StrEqual(attribName, "action", false))
|
|
{
|
|
if (VolAnticampSetActionString(dataIndex, attribValue))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if (StrEqual(attribName, "amount", false))
|
|
{
|
|
if (VolAnticampSetAmountString(dataIndex, attribValue))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if (StrEqual(attribName, "warning", false))
|
|
{
|
|
if (VolAnticampSetWarningString(dataIndex, attribValue))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if (StrEqual(attribName, "message", false))
|
|
{
|
|
// Unsupported because of technical limits in command parser. Spaces
|
|
// and quoted strings aren't supported yet.
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Parses a interval string value and applies it to the specified volume.
|
|
*
|
|
* @param dataIndex Local data index.
|
|
* @param interval Interval to set. A floating point number formatted as a
|
|
* string.
|
|
* @return True if successfully set, false otherwise.
|
|
*/
|
|
bool:VolAnticampSetIntervalString(dataIndex, const String:interval[])
|
|
{
|
|
new Float:anticampinterval;
|
|
|
|
// Check if string value is empty.
|
|
if (strlen(interval) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Convert value.
|
|
anticampinterval = StringToFloat(interval);
|
|
|
|
// Apply value.
|
|
AnticampData[dataIndex][Anticamp_Interval] = anticampinterval;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Parses a action type string value and applies it to the specified volume.
|
|
*
|
|
* @param dataIndex Local data index.
|
|
* @param action Action type to set.
|
|
* @return True if successfully set, false otherwise.
|
|
*/
|
|
bool:VolAnticampSetActionString(dataIndex, const String:action[])
|
|
{
|
|
// Check if string value is empty.
|
|
if (strlen(action) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Check effect string values and apply them to the volume.
|
|
if (StrEqual(action, "none", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Action] = Anticamp_NoAction;
|
|
return true;
|
|
}
|
|
else if (StrEqual(action, "damage", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Action] = Anticamp_Damage;
|
|
return true;
|
|
}
|
|
else if (StrEqual(action, "slay", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Action] = Anticamp_Slay;
|
|
return true;
|
|
}
|
|
else if (StrEqual(action, "drug", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Action] = Anticamp_Drug;
|
|
return true;
|
|
}
|
|
else if (StrEqual(action, "ignite", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Action] = Anticamp_Ignite;
|
|
return true;
|
|
}
|
|
|
|
// The string value didn't match any valid action types.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Parses a action amount string value and applies it to the specified volume.
|
|
*
|
|
* @param dataIndex Local data index.
|
|
* @param amount Amount to set. A floating point number formatted as a
|
|
* string.
|
|
* @return True if successfully set, false otherwise.
|
|
*/
|
|
bool:VolAnticampSetAmountString(dataIndex, const String:amount[])
|
|
{
|
|
new Float:actionamount;
|
|
|
|
// Check if string value is empty.
|
|
if (strlen(amount) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Convert value.
|
|
actionamount = StringToFloat(amount);
|
|
|
|
// Apply value.
|
|
AnticampData[dataIndex][Anticamp_Amount] = actionamount;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Parses a warning type string value and applies it to the specified volume.
|
|
*
|
|
* @param dataIndex Local data index.
|
|
* @param warning warning type to set.
|
|
* @return True if successfully set, false otherwise.
|
|
*/
|
|
bool:VolAnticampSetWarningString(dataIndex, const String:warning[])
|
|
{
|
|
|
|
// Check if string value is empty.
|
|
if (strlen(warning) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Check effect string values and apply them to the volume.
|
|
if (StrEqual(warning, "none", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Warning] = Anticamp_NoWarning;
|
|
return true;
|
|
}
|
|
else if (StrEqual(warning, "chat", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Warning] = Anticamp_Chat;
|
|
return true;
|
|
}
|
|
else if (StrEqual(warning, "center", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Warning] = Anticamp_Center;
|
|
return true;
|
|
}
|
|
else if (StrEqual(warning, "menu", false))
|
|
{
|
|
AnticampData[dataIndex][Anticamp_Warning] = Anticamp_Menu;
|
|
return true;
|
|
}
|
|
|
|
// The string value didn't match any valid action types.
|
|
return false;
|
|
}
|