Merged heads.
This commit is contained in:
commit
f126d181aa
@ -58,7 +58,8 @@
|
||||
#include "zr/zspawn"
|
||||
#include "zr/ztele"
|
||||
#include "zr/zhp"
|
||||
//#include "zr/anticamp"
|
||||
#include "zr/jumpboost"
|
||||
#include "zr/volfeatures/volfeatures"
|
||||
|
||||
// Almost replaced! :)
|
||||
#include "zr/zombie"
|
||||
|
@ -76,6 +76,7 @@ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadc
|
||||
SEffectsOnRoundStart();
|
||||
AntiStickOnRoundStart();
|
||||
ZSpawnOnRoundStart();
|
||||
VolOnRoundStart();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,6 +116,7 @@ public Action:EventRoundEnd(Handle:event, const String:name[], bool:dontBroadcas
|
||||
SEffectsOnRoundEnd();
|
||||
RespawnOnRoundEnd();
|
||||
ZSpawnOnRoundEnd();
|
||||
VolOnRoundEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
|
26
src/zr/volfeatures/volanticamp.inc
Normal file
26
src/zr/volfeatures/volanticamp.inc
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* ============================================================================
|
||||
*
|
||||
* Zombie:Reloaded
|
||||
*
|
||||
* File: volanticamp.inc
|
||||
* Type: Module
|
||||
* Description: Anti-camp handler.
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data structure for a anti-camp volume.
|
||||
*/
|
||||
enum VolTypeAnticamp
|
||||
{
|
||||
anticamp_damage,
|
||||
anticamp_interval,
|
||||
Handle:anticamp_timer
|
||||
}
|
||||
|
||||
/**
|
||||
* Anti-camp data.
|
||||
*/
|
||||
new AnticampData[ZR_VOLUMES_MAX][VolTypeAnticamp];
|
70
src/zr/volfeatures/volevents.inc
Normal file
70
src/zr/volfeatures/volevents.inc
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* ============================================================================
|
||||
*
|
||||
* Zombie:Reloaded
|
||||
*
|
||||
* File: volevents.inc
|
||||
* Type: Module
|
||||
* Description: Handles volumetric feature events.
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called when a player enters a volume.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param volumeIndex The volume index.
|
||||
*/
|
||||
VolOnPlayerEnter(client, volumeIndex)
|
||||
{
|
||||
// TODO: Check if volfeatures is enabled first.
|
||||
|
||||
// Forward event to features.
|
||||
// VolAnticampStart(client, volume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player leaves a volume.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param volumeIndex The volume index.
|
||||
*/
|
||||
VolOnPlayerLeave(client, volumeIndex)
|
||||
{
|
||||
// TODO: Check if volfeatures is enabled first.
|
||||
|
||||
// Forward event to features.
|
||||
// VolAnticampStop(client, volume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player spawned. Used for initializing player data.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
VolOnPlayerSpawn(client)
|
||||
{
|
||||
VolUpdatePlayerLocation(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the round starts. Main enable event for volumetric features.
|
||||
*/
|
||||
VolOnRoundStart()
|
||||
{
|
||||
// Start main timer.
|
||||
VolStartUpdateTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the round ends. Main disable event for volumetric features.
|
||||
*/
|
||||
VolOnRoundEnd()
|
||||
{
|
||||
// Stop main timer.
|
||||
VolStopUpdateTimer();
|
||||
|
||||
// Forward stop event to features.
|
||||
// VolAnticampStop();
|
||||
}
|
356
src/zr/volfeatures/volfeatures.inc
Normal file
356
src/zr/volfeatures/volfeatures.inc
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
* ============================================================================
|
||||
*
|
||||
* Zombie:Reloaded
|
||||
*
|
||||
* File: volfeatures.inc
|
||||
* Type: Module
|
||||
* Description: Provides functions for managing volumetric features.
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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_in_use, /** Marks if the volume is used. */
|
||||
|
||||
/* Location */
|
||||
Float:vol_x_min, /** Minimum x position. */
|
||||
Float:vol_x_max, /** Maximum x position. */
|
||||
|
||||
Float:vol_y_min, /** Minimum y position. */
|
||||
Float:vol_y_max, /** Maximum y position. */
|
||||
|
||||
Float:vol_z_min, /** Minimum z position. */
|
||||
Float:vol_z_max, /** Maximum z position. */
|
||||
|
||||
/* Data */
|
||||
VolumeEffects:vol_effect, /** Visual effect to apply on the volume. */
|
||||
VolumeFeatureTypes:vol_type, /** The volumetric feature type. */
|
||||
vol_data_index /** Index in remote feature array. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Available volumetric feature types.
|
||||
*/
|
||||
enum VolumeFeatureTypes
|
||||
{
|
||||
VolFeature_Anticamp = 0,
|
||||
VolFeature_Knockback
|
||||
}
|
||||
|
||||
enum VolumeEffects
|
||||
{
|
||||
VolEffect_None = 0,
|
||||
VolEffect_Wireframe,
|
||||
VolEffect_Smoke
|
||||
}
|
||||
|
||||
/**
|
||||
* 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];
|
||||
|
||||
/**
|
||||
* Specifies whether the volumetric features module is enabled or not. To be
|
||||
* synced with zr_volfeatures_enabled CVAR.
|
||||
*/
|
||||
new bool:VolEnabled;
|
||||
|
||||
/**
|
||||
* Timer handle for 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.
|
||||
*/
|
||||
new Handle:hVolUpdateTimer;
|
||||
|
||||
#include "zr/volfeatures/volevents"
|
||||
#include "zr/volfeatures/volanticamp"
|
||||
|
||||
/**
|
||||
* Starts the update timer.
|
||||
*/
|
||||
bool:VolStartUpdateTimer()
|
||||
{
|
||||
// TODO: Read from CVAR (zr_volfeatures_enabled).
|
||||
VolEnabled = true;
|
||||
|
||||
if (!VolEnabled)
|
||||
{
|
||||
// Volumetric features disabled.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Read from CVAR (zr_volfeatures_interval).
|
||||
new Float:interval = 1.0;
|
||||
|
||||
// Validate interval.
|
||||
if (interval > 0.0)
|
||||
{
|
||||
// Stop timer if it exist.
|
||||
VolStopUpdateTimer();
|
||||
|
||||
// Create a new timer.
|
||||
hVolUpdateTimer = CreateTimer(interval, Event_VolUpdateTimer, _, TIMER_REPEAT);
|
||||
|
||||
// Volumetric features started.
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Volumetric features disabled. Do explicit stop.
|
||||
VolStopUpdateTimer();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (new 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;
|
||||
|
||||
for (new client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
// Check if client is in game and alive.
|
||||
if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current volume states.
|
||||
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 < VolumeCount; volumeIndex++)
|
||||
{
|
||||
newState = volumeNewStates[volumeIndex];
|
||||
oldState = volumeStates[volumeIndex];
|
||||
|
||||
// Compare new states with old states.
|
||||
if (newState == oldState)
|
||||
{
|
||||
// No change. Skip to next volume.
|
||||
break;
|
||||
}
|
||||
else if (!newState && oldState)
|
||||
{
|
||||
// Client entered volume. Trigger event.
|
||||
VolOnPlayerEnter(client, volumeIndex);
|
||||
}
|
||||
else if (newState && !oldState)
|
||||
{
|
||||
// Client left the volume. Trigger event.
|
||||
VolOnPlayerLeave(client, volumeIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wether a position is within a certain location.
|
||||
*
|
||||
* @param loc The position 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:IsPositionInLocation(Float:pos[3], Float:min[3], Float:max[3])
|
||||
{
|
||||
// Cache location to avoid re-indexing arrays.
|
||||
new Float:posX = pos[0];
|
||||
new Float:posY = pos[1];
|
||||
new Float:posZ = pos[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 player is within the location boundaries.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The player is outside the location boundaries.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wether a volume is marked as in use.
|
||||
*
|
||||
* @param volumeIndex The volume index.
|
||||
* @return True if in use, false otherwise.
|
||||
*/
|
||||
bool:VolIsInUse(volumeIndex)
|
||||
{
|
||||
return Volumes[volumeIndex][vol_in_use];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (!VolIsInUse(volumeIndex))
|
||||
{
|
||||
return volumeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// No free volumes found.
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 < VolumeCount && volumeIndex < maxlen; volumeIndex++)
|
||||
{
|
||||
if (VolIsInUse(volumeIndex))
|
||||
{
|
||||
// Chache volume to avoid re-indexing.
|
||||
volumeBuffer = Volumes[volumeIndex];
|
||||
|
||||
// Get min positions.
|
||||
volMinBuffer[0] = volumeBuffer[vol_x_min];
|
||||
volMinBuffer[1] = volumeBuffer[vol_y_min];
|
||||
volMinBuffer[2] = volumeBuffer[vol_z_min];
|
||||
|
||||
// Get max positions.
|
||||
volMaxBuffer[0] = volumeBuffer[vol_x_min];
|
||||
volMaxBuffer[1] = volumeBuffer[vol_y_min];
|
||||
volMaxBuffer[2] = volumeBuffer[vol_z_min];
|
||||
|
||||
// Check the cached player location.
|
||||
if (IsPositionInLocation(VolPlayerLoc[client], volMinBuffer, volMaxBuffer))
|
||||
{
|
||||
// Mark player as in volume.
|
||||
buffer[volumeIndex] = true;
|
||||
volCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do explicit reset.
|
||||
buffer[volumeIndex] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return volCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for update timer. This is the main timer in volumetric features.
|
||||
*/
|
||||
public Action:Event_VolUpdateTimer(Handle:timer)
|
||||
{
|
||||
VolUpdatePlayerChanges();
|
||||
}
|
Loading…
Reference in New Issue
Block a user