From 1f38e9c5ac1d38aaed71084b694cc21cc2304764 Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 17 Jul 2009 18:15:44 +0200 Subject: [PATCH] Fixed bugs in volfeatures. See details. Fixed some anticamp bugs. Warning types confirmed working: chat, center, menu (minior bug: the warning text is item no. 2). Fixed base event handler bugs. Added validation warnings on anticamp intervals in case of invalid intervals. Fixed volume states not properly cleaned up when players die or disconnect. --- .../translations/zombiereloaded.phrases.txt | 10 +- src/zr/event.inc | 1 + src/zr/volfeatures/volanticamp.inc | 156 ++++++++++++------ src/zr/volfeatures/volcommands.inc | 4 +- src/zr/volfeatures/volevents.inc | 49 ++++++ src/zr/volfeatures/volfeatures.inc | 57 ++++++- 6 files changed, 215 insertions(+), 62 deletions(-) diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index 78cff2f..119664a 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -1104,6 +1104,12 @@ "Vol Slay" { "#format" "{1:s},{2:d}" - "en" "Player \"{1}\" has been slayed for camping in a restricted area (ID: {2})." + "en" "Slayed player \"{1}\" for camping in a restricted area (ID: {2})." } -} \ No newline at end of file + + "Vol Ignite" + { + "#format" "{1:s},{2:d}" + "en" "Ignited player \"{1}\" for camping in a restricted area (ID: {2})." + } +} diff --git a/src/zr/event.inc b/src/zr/event.inc index ed93272..05f9325 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -282,6 +282,7 @@ public Action:EventPlayerDeath(Handle:event, const String:name[], bool:dontBroad ZSpawnOnClientDeath(index); ZTeleOnClientDeath(index); ZHPOnClientDeath(index); + VolOnPlayerDeath(index); } /** diff --git a/src/zr/volfeatures/volanticamp.inc b/src/zr/volfeatures/volanticamp.inc index d99fe98..e8f6dd4 100644 --- a/src/zr/volfeatures/volanticamp.inc +++ b/src/zr/volfeatures/volanticamp.inc @@ -77,6 +77,7 @@ new AnticampData[ZR_VOLUMES_MAX][VolTypeAnticamp]; VolAnticampEnable(volumeIndex) { new Float:interval; + new Handle:timer; // Validate index. if (!VolIsValidIndex(volumeIndex)) @@ -96,20 +97,27 @@ VolAnticampEnable(volumeIndex) // Check if in use. if (AnticampData[dataindex][Anticamp_InUse]) { - // Start timer if not running. - if (AnticampData[dataindex][Anticamp_Timer] == INVALID_HANDLE) + // Kill timer if it exist. + timer = AnticampData[dataindex][Anticamp_Timer]; + if (timer != INVALID_HANDLE) { - // Get interval. - interval = AnticampData[dataindex][Anticamp_Interval]; - - // Validate interval. - if (interval > 0.0) - { - AnticampData[dataindex][Anticamp_Timer] = CreateTimer(interval, Event_VolAnticampTrigger, _, TIMER_REPEAT); - } + KillTimer(timer); + AnticampData[dataindex][Anticamp_Timer] = INVALID_HANDLE; } - LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Vol state", "Enabled anticamp volume %d.", volumeIndex); + // Get interval. + interval = AnticampData[dataindex][Anticamp_Interval]; + + // Validate interval. + if (interval > 0.0) + { + AnticampData[dataindex][Anticamp_Timer] = CreateTimer(interval, Event_VolAnticampTrigger, volumeIndex, TIMER_REPEAT); + 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); + } } } @@ -119,24 +127,44 @@ VolAnticampEnable(volumeIndex) stock VolAnticampEnableAll() { new Float:interval; + new dataindex; // Loop through all volumes. - for (new dataindex = 0; dataindex < ZR_VOLUMES_MAX; dataindex++) + for (new volumeindex = 0; volumeindex < ZR_VOLUMES_MAX; volumeindex++) { - // Check if in use. - if (AnticampData[dataindex][Anticamp_InUse]) + // Check if unused. + if (!VolInUse(volumeindex)) { - // Start timer if not running. - if (AnticampData[dataindex][Anticamp_Timer] == INVALID_HANDLE) + // 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) { - // Get interval. - interval = AnticampData[dataindex][Anticamp_Interval]; - - // Validate interval. - if (interval > 0.0) - { - AnticampData[dataindex][Anticamp_Timer] = CreateTimer(interval, Event_VolAnticampTrigger, _, TIMER_REPEAT); - } + 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); + 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); } } } @@ -242,23 +270,37 @@ VolAnticampInit() /** * Timer callback for anticamp volumes. Applies actions on players in volumes. */ -public Action:Event_VolAnticampTrigger(Handle:timer) +public Action:Event_VolAnticampTrigger(Handle:timer, any:volumeIndex) { // Loop through all players. for (new client = 1; client <= MaxClients; client++) { - // Loop through all volumes. - for (new volumeindex = 0; volumeindex < ZR_VOLUMES_MAX; volumeindex++) + // Validate client's connection state. + if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client)) { - // Check if the volume is enabled and in use. - if (VolIsEnabled(volumeindex) && VolInUse(volumeindex)) + 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]) { - // Check if player is in a anticamp volume. - if (VolPlayerInVolume[client][volumeindex] && Volumes[volumeindex][Vol_Type] == VolFeature_Anticamp) - { - // Apply action. - VolAnticampApplyAction(client, Volumes[volumeindex][Vol_DataIndex], volumeindex); - } + // Apply action. + VolAnticampApplyAction(client, Volumes[volumeIndex][Vol_DataIndex], volumeIndex); } } } @@ -275,6 +317,13 @@ 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); @@ -286,11 +335,9 @@ VolAnticampApplyAction(client, dataIndex, volumeIndex) } case Anticamp_Damage: { - // Give damage to player. Kill if zero HP. + // Give damage to player. Kill if zero HP or below. new damage = RoundToNearest(amount); new health = GetClientHealth(client) - damage; - decl String:name[64]; - decl String:buffer[256]; if (health > 0) { @@ -302,29 +349,32 @@ VolAnticampApplyAction(client, dataIndex, volumeIndex) ForcePlayerSuicide(client); // Log event. - GetClientName(client, name, sizeof(name)); - SetGlobalTransTarget(client); - Format(buffer, sizeof(buffer), "%t", "Vol Slay", name, volumeIndex); - - /*if (LogFlagCheck(LOG_GAME_EVENTS, LOG_MODULE_ANTICAMP)) ZR_LogMessageFormatted(client, "anticamp", "kill", "%s", true, buffer); - if (anticamp_echo) - { - FormatTextString(buffer, sizeof(buffer)); - ZR_PrintToAdminChat(buffer); - }*/ + 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) + { + // 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); + } } } } @@ -351,7 +401,7 @@ VolAnticampWarnPlayer(client, dataIndex) } else { - // Use message in translations file. + // Use default anticamp message in translations file. Format(buffer, sizeof(buffer), "%t", "Vol Anticamp Message"); } @@ -415,6 +465,10 @@ VolAnticampGetFreeIndex() // 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; } } diff --git a/src/zr/volfeatures/volcommands.inc b/src/zr/volfeatures/volcommands.inc index 4488ba8..9e1c535 100644 --- a/src/zr/volfeatures/volcommands.inc +++ b/src/zr/volfeatures/volcommands.inc @@ -223,7 +223,6 @@ public Action:VolAddVolumeCommand(client, argc) // Set attributes. paramcount = VolSetAttributes(volindex, params); - LogEvent(_, LogType_Normal, LOG_DEBUG, LogModule_Volfeatures, "Add volume", "Parsing parameter string. Param count = \"%d\". String = \"%s\"", paramcount, params); } else { @@ -240,6 +239,9 @@ public Action:VolAddVolumeCommand(client, argc) Format(buffer, sizeof(buffer), "Additional attributes set: %d", paramcount); } + // Send enable event to volume. + VolOnEnabled(volindex); + ReplyToCommand(client, "Added volume at index %d. %s", volindex, buffer); return Plugin_Handled; } diff --git a/src/zr/volfeatures/volevents.inc b/src/zr/volfeatures/volevents.inc index 33f1398..eed16d2 100644 --- a/src/zr/volfeatures/volevents.inc +++ b/src/zr/volfeatures/volevents.inc @@ -85,6 +85,38 @@ VolOnPlayerSpawn(client) VolUpdatePlayerLocation(client); } +/** + * Called when a player died. + * + * @param client The client index. + */ +VolOnPlayerDeath(client) +{ + // Send player left volume event to all volumes the player was in. + for (new volindex = 0; volindex < ZR_VOLUMES_MAX; volindex++) + { + // Check if volume is unused. + if (!Volumes[volindex][Vol_InUse]) + { + continue; + } + + // Check if volume is disabled. + if (!Volumes[volindex][Vol_Enabled]) + { + continue; + } + + // Check if player is inside the volume. + if (VolPlayerInVolume[client][volindex]) + { + // Mark as not in the volume and trigger event. + VolPlayerInVolume[client][volindex] = false; + VolOnPlayerLeave(client, volindex); + } + } +} + /** * Called when a player disconnects. * @@ -94,6 +126,9 @@ VolOnPlayerDisconnect(client) { // Disable trigger delay counters. VolResetCountDown(client); + + // Trigger death event to clean up. + VolOnPlayerDeath(client); } /** @@ -133,6 +168,13 @@ VolOnRoundEnd() */ VolOnDisabled(volumeIndex) { + // Check if volumetric features is enabled. + if (!VolEnabled) + { + // Volumetric features disabled. + return; + } + new VolumeFeatureTypes:voltype = Volumes[volumeIndex][Vol_Type]; // Forward stop event to features. @@ -151,6 +193,13 @@ VolOnDisabled(volumeIndex) */ VolOnEnabled(volumeIndex) { + // Check if volumetric features is enabled. + if (!VolEnabled) + { + // Volumetric features disabled. + return; + } + new VolumeFeatureTypes:voltype = Volumes[volumeIndex][Vol_Type]; // Forward stop event to features. diff --git a/src/zr/volfeatures/volfeatures.inc b/src/zr/volfeatures/volfeatures.inc index 1f67dfd..9f13f83 100644 --- a/src/zr/volfeatures/volfeatures.inc +++ b/src/zr/volfeatures/volfeatures.inc @@ -195,6 +195,28 @@ VolDisableVolumes() { if (Volumes[volindex][Vol_InUse] && Volumes[volindex][Vol_Enabled]) { + // Mark as disabled. + Volumes[volindex][Vol_Enabled] = false; + + // Trigger player left volume event if inside a volume. + for (new client = 1; client <= MaxClients; client++) + { + // Validate client's connection state. + if (!IsClientConnected(client) || !IsClientInGame(client)) + { + continue; + } + + // Check if player is inside the volume. + if (VolPlayerInVolume[client][volindex]) + { + // Mark as not in the volume and trigger event. + VolPlayerInVolume[client][volindex] = false; + VolOnPlayerLeave(client, volindex); + } + } + + // Trigger disabled event. VolOnDisabled(volindex); } } @@ -210,6 +232,7 @@ VolEnableVolumes() { if (Volumes[volindex][Vol_InUse] && !Volumes[volindex][Vol_Enabled]) { + Volumes[volindex][Vol_Enabled] = true; VolOnEnabled(volindex); } } @@ -367,10 +390,10 @@ VolUpdatePlayerLocation(client = -1) { for (client = 1; client <= MaxClients; client++) { - // Check if client is in game and alive. + // Validate client's connection state. if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client)) { - return; + continue; } // Save location in array. @@ -396,7 +419,7 @@ VolUpdatePlayerChanges() // Loop through all players. for (new client = 1; client <= MaxClients; client++) { - // Check if client is in game and alive. + // Validate client's connection state. if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client)) { // Skip client. @@ -467,11 +490,17 @@ VolUpdatePlayerChanges() // Make sure count down value is reset. VolPlayerCountDown[client][volumeIndex] = -1.0; - // Update cache. - VolPlayerInVolume[client][volumeIndex] = false; - - // Trigger event. - VolOnPlayerLeave(client, volumeIndex); + // Only trigger left volume event if player already is in the + // volume, so volumes with trigger delay won't get a left event + // before the enter event. + if (VolPlayerInVolume[client][volumeIndex]) + { + // Update cache. + VolPlayerInVolume[client][volumeIndex] = false; + + // Trigger event. + VolOnPlayerLeave(client, volumeIndex); + } } } } @@ -641,6 +670,18 @@ bool:VolTeamFilterMatch(client, volumeIndex) return false; } +/** + * Checs if a volume is a certain type. + * + * @param volumeIndex Volume to check. + * @param volType Type to match. + * @return True if the types match, false otherwise. + */ +bool:VolIsType(volumeIndex, VolumeFeatureTypes:volType) +{ + return Volumes[volumeIndex][Vol_Type] == volType; +} + /** * Gets wether a client is within volumes or not. Result is stored in a boolean * array.