Junior Member
|
03-04-2015
, 15:45
Re: Counting and finding zombies in L4D2
|
#13
|
Okay, so I've written most of the code but I'm getting a couple of errors related to the arrays I'm using. Can anybody help resolve them? I have no idea what is wrong.
Also, bonus points for anything else that isn't done right. This is my first plugin so there is a good chance that's the case.
EDIT: Fixed the array issues, now I'm getting some other errors.
My code:
PHP Code:
/****************************************************************************************/
/* INCLUDES */
/****************************************************************************************/
#include <sourcemod>
#include <sdktools>
/****************************************************************************************/
/* PLUGIN INFORMATION */
/****************************************************************************************/
public Plugin:myinfo = {
name = "Bots use throwables",
author = "Qub1 ([email protected])",
description = "Allows bots to pick up and use throwables.",
version = "1.0.0",
url = "http://qub1.infohoarder.com/"
};
/****************************************************************************************/
/* TODO */
/****************************************************************************************/
/**
* - Add grabbing timer
* - Finish throwing functions
* - Add special infected responses
* - Target special infected before common infected
* - Properly stop all timers on round end to prevent crashes
*/
/****************************************************************************************/
/* MODEL FILES */
/****************************************************************************************/
#define MODEL_MOLOTOV "models/w_models/weapons/w_eq_molotov.mdl"
#define MODEL_COACH "models/survivors/survivor_coach.mdl"
#define MODEL_ELLIS "models/survivors/survivor_mechanic.mdl"
#define MODEL_NICK "models/survivors/survivor_gambler.mdl"
#define MODEL_ROCHELLE "models/survivors/survivor_producer.mdl"
/****************************************************************************************/
/* SOUND FILES */
/****************************************************************************************/
#define SOUND_MOLOTOV "weapons/molotov/fire_ignite_2.wav"
/****************************************************************************************/
/* VOICE FILES - TAKING GRENADE */
/****************************************************************************************/
new String:s_CoachTakeMolotov[2][] = {
"scenes/coach/takemolotov01.vcd",
"scenes/coach/takemolotov02.vcd"
};
new String:s_CoachTakePipebomb[3][] = {
"scenes/coach/takepipebomb01.vcd",
"scenes/coach/takepipebomb02.vcd",
"scenes/coach/takepipebomb03.vcd"
};
new String:s_CoachTakeVomitjar[0][] = {};
new String:s_EllisTakeMolotov[8][] = {
"scenes/mechanic/takemolotov01.vcd",
"scenes/mechanic/takemolotov02.vcd",
"scenes/mechanic/takemolotov03.vcd",
"scenes/mechanic/takemolotov04.vcd",
"scenes/mechanic/takemolotov05.vcd",
"scenes/mechanic/takemolotov06.vcd",
"scenes/mechanic/takemolotov07.vcd",
"scenes/mechanic/takemolotov08.vcd"
};
new String:s_EllisTakePipebomb[3][] = {
"scenes/mechanic/takepipebomb01.vcd",
"scenes/mechanic/takepipebomb02.vcd",
"scenes/mechanic/takepipebomb03.vcd"
};
new String:s_EllisTakeVomitjar[0][] = {};
new String:s_NickTakeMolotov[2][] = {
"scenes/gambler/takemolotov01.vcd",
"scenes/gambler/takemolotov02.vcd"
};
new String:s_NickTakePipebomb[2][] = {
"scenes/gambler/takepipebomb01.vcd",
"scenes/gambler/takepipebomb02.vcd"
};
new String:s_NickTakeVomitjar[0][] = {};
new String:s_RochelleTakeMolotov[4][] = {
"scenes/producer/takemolotov01.vcd",
"scenes/producer/takemolotov02.vcd",
"scenes/producer/takemolotov03.vcd",
"scenes/producer/takemolotov04.vcd"
};
new String:s_RochelleTakePipebomb[2][] = {
"scenes/producer/takepipebomb01.vcd",
"scenes/producer/takepipebomb02.vcd"
};
new String:s_RochelleTakeVomitjar[0][] = {};
/****************************************************************************************/
/* VOICE FILES - THROWING GRENADE */
/****************************************************************************************/
new String:s_CoachThrowMolotov[3][] = {
"scenes/coach/grenade02.vcd",
"scenes/coach/grenade04.vcd",
"scenes/coach/grenade05.vcd"
};
new String:s_CoachThrowPipebomb[6][] = {
"scenes/coach/grenade01.vcd",
"scenes/coach/grenade03.vcd",
"scenes/coach/grenade06.vcd",
"scenes/coach/grenade07.vcd",
"scenes/coach/grenade11.vcd",
"scenes/coach/grenade12.vcd"
};
new String:s_CoachThrowVomitjar[3][] = {
"scenes/coach/boomerjar09.vcd",
"scenes/coach/boomerjar10.vcd",
"scenes/coach/boomerjar11.vcd"
};
new String:s_EllisThrowMolotov[4][] = {
"scenes/mechanic/grenade05.vcd",
"scenes/mechanic/grenade06.vcd",
"scenes/mechanic/grenade08.vcd",
"scenes/mechanic/grenade10.vcd"
};
new String:s_EllisThrowPipebomb[8][] = {
"scenes/mechanic/grenade01.vcd",
"scenes/mechanic/grenade02.vcd",
"scenes/mechanic/grenade03.vcd",
"scenes/mechanic/grenade07.vcd",
"scenes/mechanic/grenade09.vcd",
"scenes/mechanic/grenade11.vcd",
"scenes/mechanic/grenade12.vcd",
"scenes/mechanic/grenade13.vcd"
};
new String:s_EllisThrowVomitjar[6][] = {
"scenes/mechanic/boomerjar08.vcd",
"scenes/mechanic/boomerjar09.vcd",
"scenes/mechanic/boomerjar10.vcd",
"scenes/mechanic/boomerjar12.vcd",
"scenes/mechanic/boomerjar13.vcd",
"scenes/mechanic/boomerjar14.vcd"
};
new String:s_NickThrowMolotov[4][] = {
"scenes/gambler/grenade03.vcd",
"scenes/gambler/grenade04.vcd",
"scenes/gambler/grenade06.vcd",
"scenes/gambler/grenade08.vcd"
};
new String:s_NickThrowPipebomb[7][] = {
"scenes/gambler/grenade01.vcd",
"scenes/gambler/grenade02.vcd",
"scenes/gambler/grenade05.vcd",
"scenes/gambler/grenade07.vcd",
"scenes/gambler/grenade09.vcd",
"scenes/gambler/grenade11.vcd",
"scenes/gambler/grenade13.vcd"
};
new String:s_NickThrowVomitjar[3][] = {
"scenes/gambler/boomerjar08.vcd",
"scenes/gambler/boomerjar09.vcd",
"scenes/gambler/boomerjar10.vcd"
};
new String:s_RochelleThrowMolotov[3][] = {
"scenes/producer/grenade03.vcd",
"scenes/producer/grenade04.vcd",
"scenes/producer/grenade06.vcd"
};
new String:s_RochelleThrowPipebomb[4][] = {
"scenes/producer/grenade01.vcd",
"scenes/producer/grenade02.vcd",
"scenes/producer/grenade05.vcd",
"scenes/producer/grenade07.vcd"
};
new String:s_RochelleThrowVomitjar[3][] = {
"scenes/producer/boomerjar07.vcd",
"scenes/producer/boomerjar08.vcd",
"scenes/producer/boomerjar09.vcd"
};
/****************************************************************************************/
/* WEAPON SLOTS */
/****************************************************************************************/
#define WEAPONSLOTS_COUNT 5
enum WEAPONSLOTS {
WEAPONSLOT_PRIMARY = 0, // Assault rifles, machine guns, chainsaws
WEAPONSLOT_SECONDARY = 1, // Pistols, melee weapons
WEAPONSLOT_GRENADE = 2, // Pipebombs, molotovs and vomitjars
WEAPONSLOT_HEALTH = 3, // Health and defibrilators
WEAPONSLOT_SPECIAL = 4 // Pills and adrenaline
};
/****************************************************************************************/
/* CONVARS */
/****************************************************************************************/
new Handle:h_MaximumClientRadius,
Handle:h_HordeRadius,
Handle:h_MinimumHordeMolotov,
Handle:h_MinimumHordePipebomb,
Handle:h_MinimumHordeVomitjar,
Handle:h_MinimumInfectedPipebomb,
Handle:h_MinimumInfectedVomitjar,
Handle:h_MolotovSpeed,
Handle:h_PipebombSpeed,
Handle:h_PipebombDuration,
Handle:h_VomitjarSpeed,
Handle:h_VomitjarDuration,
Handle:h_VomitjarEffectDuration,
Handle:h_VomitjarRadius;
/****************************************************************************************/
/* GLOBAL VARIABLES */
/****************************************************************************************/
new Handle:h_GrenadeTimers[MAXPLAYERS+1];
/****************************************************************************************/
/* INITIALIZATION */
/****************************************************************************************/
public OnPluginStart() {
PrintToServer("Starting \"Bots use throwables\"...");
// Load ConVars
h_MaximumClientRadius = CreateConVar("but_maximum_client_radius", "4000", "Maximum range the AI will check for zombies (distance in inches).");
h_MinimumHordeMolotov = CreateConVar("but_horde_radius", "200", "Minimum range in which to check for zombies to see if there is a horde (distance in inches).");
h_MinimumHordeMolotov = CreateConVar("but_minimum_horde_molotov", "5", "Minimum horde size AI will throw molotovs at.");
h_MinimumHordePipebomb = CreateConVar("but_minimum_horde_pipebomb", "5", "Minimum horde size AI will throw pipebombs at (higher priority than minimum_infected_pipebomb, so AI will target hordes first).");
h_MinimumHordeVomitjar = CreateConVar("but_minimum_horde_vomitjar", "5", "Minimum horde size AI will throw vomitjars at (higher priority than minimum_infected_vomitjar, so AI will target hordes first).");
h_MinimumInfectedPipebomb = CreateConVar("but_minimum_infected_pipebomb", "10", "Minimum infected in the area for the AI to throw a pipebomb.");
h_MinimumInfectedVomitjar = CreateConVar("but_minimum_infected_vomitjar", "10", "Minimum infected in the area for the AI to throw a vomitjar.");
h_MolotovSpeed = CreateConVar("but_molotov_speed", "700", "The speed at which molotovs are thrown (in inches per second).");
h_PipebombSpeed = CreateConVar("but_pipebomb_speed", "600", "The speed at which pipebombs are thrown (in inches per second).");
h_PipebombDuration = CreateConVar("but_pipebomb_duration", "6", "How long it takes for a pipebomb to detonate (in seconds).");
h_VomitjarSpeed = CreateConVar("but_vomitjar_speed", "700", "The speed at which vomitjars are thrown (in inches per second).");
h_VomitjarDuration = CreateConVar("but_vomitjar_duration", "15", "How long the vomitjar will affect the infected (in seconds).");
h_VomitjarEffectDuration = CreateConVar("but_vomitjar_effect_duration", "20", "How long the vomitjar's effect will be visible (in seconds).");
h_VomitjarRadius = CreateConVar("but_vomitjar_radius", "110", "How far the vomitjar effect spreads from inpact (in inches).");
// Hook events
HookEvent("round_end", EventRoundEnd);
// Create the timer that checks throwing conditions
CreateTimer(3.0, Timer_CheckThrow, _, TIMER_REPEAT);
PrintToServer("Successfully started \"Bots use throwables\"!");
}
/****************************************************************************************/
/* EVENTS */
/****************************************************************************************/
public Action:EventRoundEnd(Handle:h_Event, const String:s_Name[], bool:b_DontBroadcast) {
// Kill all grenade timers
for(new i_Client = 1; i_Client <= GetMaxClients(); i_Client++) {
// Check if the client has any grenade timers
if(h_GrenadeTimers[i_Client] != INVALID_HANDLE) {
// Kill their grenade timer
KillTimer(h_GrenadeTimers[i_Client]);
h_GrenadeTimers[i_Client] = INVALID_HANDLE;
}
}
}
/****************************************************************************************/
/* AI DECISION TIMER */
/****************************************************************************************/
public Action:Timer_CheckThrow(Handle:timer) {
// Get the amount of clients
new i_MaxClients = GetMaxClients();
// Loop through all clients
for(new i_Client = 1; i_Client <= i_MaxClients; i_Client++) {
// Check if the client is in game, on the survivors team, alive, a bot, not reviving and not incapped
if(IsClientInGame(i_Client) && GetClientTeam(i_Client) == 2 && IsPlayerAlive(i_Client) && IsFakeClient(i_Client) && !ClientIsBeingRevived(i_Client) && !ClientIsIncapacitated(i_Client)) {
// Check if they have a grenade
if(ClientHasWeaponInSlot(i_Client, WEAPONSLOT_GRENADE)) {
// Get the type of grenade
decl String:s_Weapon[PLATFORM_MAX_PATH];
s_Weapon = GetClientWeaponSlotWeaponName(i_Client, WEAPONSLOT_GRENADE);
// Get all zombies
new Handle:h_Entities = GetEntitiesWithClassname("infected");
// Required buffers
decl Float:f_ClientPosition[3];
// Get client position
GetClientEyePosition(i_Client, f_ClientPosition);
// Loop through zombies and find the largest horde
new Handle:h_LargestHorde, i_LargestHordeSize = -1;
for(new i_Entity = 0; i_Entity < GetArraySize(h_Entities); i_Entity++) {
// Get zombie position
new Float:f_EntityPosition[3] = GetEntityAbsolutePosition(GetArrayCell(h_Entities, i_Entity));
// Check if the current client can see the zombie and is within reach of the client
if(OriginVisibleToTarget(f_ClientPosition, f_EntityPosition) && GetVectorDistance(f_ClientPosition, f_EntityPosition) <= h_MaximumClientRadius) {
// Create a horde array for the current zombie
new Handle:h_Horde = CreateArray();
// Add the current zombie to their own horde
PushArrayCell(h_Horde, i_Entity);
// Loop through zombies to find hordes
for(new i_HordeEntity = 0; i_HordeEntity < GetArraySize(h_Entities); i_HordeEntity++) {
// Skip the main zombie
if(GetArrayCell(h_Entities, i_Entity) != GetArrayCell(h_Entities, i_HordeEntity)) {
// Get zombie position
decl Float:f_HordeEntityPosition[3] = GetEntityAbsolutePosition(GetArrayCell(h_Entities, i_HordeEntity));
// Check if the horde zombie is visible to the client, and is within the horde radius
if(OriginVisibleToTarget(f_ClientPosition, f_HordeEntityPosition) && GetVectorDistance(f_EntityPosition, f_HordeEntityPosition) <= h_HordeRadius) {
// Add the zombie to the horde
PushArrayCell(h_Horde, GetArrayCell(h_Entities, i_HordeEntity));
}
}
}
// Check if the horde is larger than the minimum horde requirement, and larger than the largest horde
new i_HordeSize = GetArraySize(h_Horde);
if(((StrEqual(s_Weapon, "weapon_molotov") && i_HordeSize >= h_MinimumHordeMolotov) || (StrEqual(s_Weapon, "weapon_pipebomb") && i_HordeSize >= h_MinimumHordePipebomb) || (StrEqual(s_Weapon, "weapon_vomitjar") && i_HordeSize >= h_MinimumHordeVomitjar)) && i_HordeSize > i_LargestHordeSize) {
h_LargestHorde = h_Horde;
i_LargestHordeSize = i_HordeSize;
}
}
}
// Check if a horde was found, and if so execute the required actions and exit
if(i_LargestHordeSize != -1) {
// If a horde was found, find the closest zombie
new i_ClosestEntityIndex = -1, Float:f_ClosestEntityDistance = -1;
for(new i_HordeEntity = 0; i_HordeEntity < GetArraySize(h_LargestHorde); i_HordeEntity++) {
// Get the position of the horde's main zombie
decl Float:f_HordeEntityPosition[3] = GetEntityAbsolutePosition(GetArrayCell(h_LargestHorde, i_HordeEntity));
// Get the current entity's distance
new Float:f_HordeEntityDistance = GetVectorDistance(f_ClientPosition, f_HordeEntityPosition);
// Check if it is closer than the closest zombie found
if(i_HordeEntityDistance < f_ClosestEntityDistance) {
i_ClosestEntityIndex = i_HordeEntity;
f_ClosestEntityDistance = f_HordeEntityDistance;
}
}
// Determine what to do based on the weapon owned
if(StrEqual(s_Weapon, "weapon_molotov")) {
// TODO: Throw a molotov
ThrowMolotov(i_Client, GetArrayCell(h_Entities, i_ClosestEntityIndex));
} else if(StrEqual(s_Weapon, "weapon_pipebomb") {
// TODO: Throw a pipebomb
ThrowPipebomb(i_Client, GetArrayCell(h_Entities, i_ClosestEntityIndex));
} else if(StrEqual(s_Weapon, "weapon_vomitjar") {
// TODO: Throw vomitjar at largest horde
ThrowVomitjar(i_Client, GetArrayCell(h_Entities, i_ClosestEntityIndex));
}
// Exit
return;
}
// Still here? Then no suitable horde was found - execute infected count based actions
if(StrEqual(s_Weapon, "weapon_pipebomb") || StrEqual(s_Weapon, "weapon_vomitjar")) {
// Find the closest visible zombie
new i_ClosestEntityIndex = -1, Float:f_ClosestEntityDistance = -1;
for(new i_Entity = 0; i_Entity < GetArraySize(h_Entities); i_Entity++) {
// Get the position of the current entity
decl Float:f_EntityPosition[3] = GetEntityAbsolutePosition(GetArrayCell(h_Entities, i_Entity));
// Get the distance to the client
new Float:f_EntityDistance = GetVectorDistance(f_ClientPosition, f_EntityPosition);
// Check if the current client can see the zombie and is within reach of the client
if(OriginVisibleToTarget(f_ClientPosition, f_EntityPosition) && f_EntityDistance <= h_MaximumClientRadius) {
// Check if it is closer than the closest zombie found
if(f_EntityDistance < f_ClosestEntityDistance) {
i_ClosestEntityIndex = i_Entity;
f_ClosestEntityDistance = f_EntityDistance;
}
}
}
// Determine what to do based on the weapon owned
if(StrEqual(s_Weapon, "weapon_pipebomb")) {
// TODO: Throw a pipebomb
ThrowPipebomb(i_Client, GetArrayCell(h_Entities, i_ClosestEntityIndex));
} else if(StrEqual(s_Weapon, "weapon_vomitjar") {
// TODO: Throw a vomitjar
ThrowVomitjar(i_Client, GetArrayCell(h_Entities, i_ClosestEntityIndex));
}
// Exit
return;
}
}
}
}
}
/****************************************************************************************/
/* WEAPONS */
/****************************************************************************************/
/**
* Throws a molotov originating from the specified client.
*
* @param i_Client The client where the molotov should originate from.
* @param i_TargetEntity The entity the molotov should hit.
*
* @noreturn
*/
ThrowMolotov(i_Client, i_TargetEntity) {
// The scene buffer
new String:s_SceneFile[PLATFORM_MAX_PATH];
// Check the bot type
if(ClientHasModel(i_Client, MODEL_COACH)) {
// Get a random voice
s_SceneFile = s_CoachThrowMolotov[GetRandomInt(0, sizeof(s_CoachMolotov) - 1)];
} else if(ClientHasModel(i_Client, MODEL_ELLIS)) {
// Get a random voice
s_SceneFile = s_EllisThrowMolotov[GetRandomInt(0, sizeof(s_EllisMolotov) - 1)];
} else if(ClientHasModel(i_Client, MODEL_NICK)) {
// Get a random voice
s_SceneFile = s_NickThrowMolotov[GetRandomInt(0, sizeof(s_NickMolotov) - 1)];
} else if(ClientHasModel(i_Client, MODEL_ROCHELLE)) {
// Get a random voice
s_SceneFile = s_RochelleThrowMolotov[GetRandomInt(0, sizeof(s_RochelleMolotov) - 1)];
}
// Play the sound
PlayScene(i_Client, s_SceneFile);
// Create the molotov entity
new i_Entity = CreateEntityByName("molotov_projectile");
// Check if the entity is valid
if(IsValidEntity(i_Entity)) {
// Set the owner of the molotov to the bot
SetEntPropEnt(i_Entity, Prop_Data, "m_hOwnerEntity", i_Client);
// Set the model to that of a molotov
SetEntityModel(i_Entity, MODEL_MOLOTOV);
// Spawn the molotov
DispatchSpawn(i_Entity);
}
// Create the required buffers
decl Float:f_ClientPosition, Float:f_TargetEntityPosition, Float:f_RelativePosition[3], Float:f_Angles[3], Float:f_Speed[3];
// Get the position of the client
GetClientEyePosition(i_Client, f_ClientPosition);
// Get the position of the target
f_TargetEntityPosition = GetEntityAbsolutePosition(i_TargetEntity);
// Compute the vector from the client to the target
MakeVectorFromPoints(f_ClientPosition, f_TargetEntityPosition, f_RelativePosition);
// Get the angle from the vector calculated above
GetVectorAngles(f_RelativePosition, f_Angles);
// Get the speed
GetVectorAngles(f_Angles, f_Speed);
// Set the speed of the molotov
f_Speed[0] *= h_MolotovSpeed;
f_Speed[1] *= h_MolotovSpeed;
f_Speed[2] *= h_MolotovSpeed;
// Get some random angles (the starting position of the molotov)
f_Angles = GetRandomAngles();
// Put the molotov at the correct position
TeleportEntity(i_Entity, f_ClientPosition, f_Angles, f_Speed);
// Emit molotov sound
EmitSoundToAll(SOUND_MOLOTOV, i_Entity, SNDCHAN_WEAPON, SNDLEVEL_TRAFFIC, SND_NOFLAGS, SNDVOL_NORMAL, 100, _, f_ClientPosition, NULL_VECTOR, false, 0.0);
// Create the timer that moves the molotov
h_GrenadeTimers[i_Client] = CreateTimer(0.1, MolotovLogic, i_Entity, TIMER_REPEAT);
}
/**
* Molotov logic timer.
*
* @noreturn
*/
public Action:MolotovLogic(Handle:h_Timer, any:i_Entity) {
// Required buffers
decl String:s_Classname[PLATFORM_MAX_PATH];
// Get the owner of the entity
new i_Client = GetEntPropEnt(i_Entity, Prop_Data, "m_hOwnerEntity");
// Get the classname of the entity
GetEntityClassname(i_Entity, s_Classname, sizeof(s_Classname));
// Check if the grenade still exists
if(!IsValidEntity(i_Entity) || StrContains(s_Classname, "projectile") == -1) {
// If not, kill the timer and exit
if(h_GrenadeTimers[i_Client] != INVALID_HANDLE) {
KillTimer(h_GrenadeTimers[i_Client]);
h_GrenadeTimers[i_Client] = INVALID_HANDLE;
}
return Plugin_Handled;
}
}
/**
* Throws a pipebomb originating from the specified client.
*
* @param i_Client The client where the pipebomb should originate from.
* @param i_TargetEntity The entity the pipebomb should hit.
*
* @noreturn
*/
ThrowPipebomb(i_Client, i_TargetEntity) {
// The scene buffer
new String:s_SceneFile[PLATFORM_MAX_PATH];
// Check the bot type
if(ClientHasModel(i_Client, MODEL_COACH)) {
// Get a random voice
s_SceneFile = s_CoachThrowPipebomb[GetRandomInt(0, sizeof(s_CoachPipebomb) - 1)];
} else if(ClientHasModel(i_Client, MODEL_ELLIS)) {
// Get a random voice
s_SceneFile = s_EllisThrowPipebomb[GetRandomInt(0, sizeof(s_EllisPipebomb) - 1)];
} else if(ClientHasModel(i_Client, MODEL_NICK)) {
// Get a random voice
s_SceneFile = s_NickThrowPipebomb[GetRandomInt(0, sizeof(s_NickPipebomb) - 1)];
} else if(ClientHasModel(i_Client, MODEL_ROCHELLE)) {
// Get a random voice
s_SceneFile = s_RochelleThrowPipebomb[GetRandomInt(0, sizeof(s_RochellePipebomb) - 1)];
}
// Play the sound
PlayScene(i_Client, s_SceneFile);
// TODO: Implement actual grenade
}
/**
* Throws a vomitjar originating from the specified client.
*
* @param i_Client The client where the vomitjar should originate from.
* @param i_TargetEntity The entity the vomitjar should hit.
*
* @noreturn
*/
ThrowVomitjar(i_Client, i_TargetEntity) {
// The scene buffer
new String:s_SceneFile[PLATFORM_MAX_PATH];
// Check the bot type
if(ClientHasModel(i_Client, MODEL_COACH)) {
// Get a random voice
s_SceneFile = s_CoachThrowVomitjar[GetRandomInt(0, sizeof(s_CoachVomitjar) - 1)];
} else if(ClientHasModel(i_Client, MODEL_ELLIS)) {
// Get a random voice
s_SceneFile = s_EllisThrowVomitjar[GetRandomInt(0, sizeof(s_EllisVomitjar) - 1)];
} else if(ClientHasModel(i_Client, MODEL_NICK)) {
// Get a random voice
s_SceneFile = s_NickThrowVomitjar[GetRandomInt(0, sizeof(s_NickVomitjar) - 1)];
} else if(ClientHasModel(i_Client, MODEL_ROCHELLE)) {
// Get a random voice
s_SceneFile = s_RochelleThrowVomitjar[GetRandomInt(0, sizeof(s_RochelleVomitjar) - 1)];
}
// Play the sound
PlayScene(i_Client, s_SceneFile);
// TODO: Implement actual grenade
}
/****************************************************************************************/
/* VOCALIZATION */
/****************************************************************************************/
/**
* Plays the scene in the specified file.
*
* @param i_Client The client where the scene originates from.
* @param s_SceneFile The scene file to play.
*
* @noreturn
*/
PlayScene(i_Client, String:s_SceneFile[]) {
// Create a new scene entity
new i_SceneEntity = CreateEntityByName("instanced_scripted_scene");
// Set the entity's scene file
DispatchKeyValue(i_SceneEntity, "SceneFile", s_SceneFile);
// Spawn the entity
DispatchSpawn(i_SceneEntity);
// Set the owner of the entity to a specific client
SetEntPropEnt(i_SceneEntity, Prop_Data, "m_hOwner", i_Client);
// Activate the scene
ActivateEntity(i_SceneEntity);
// Start the scene
AcceptEntityInput(i_SceneEntity, "Start", i_Client, i_Client);
}
/****************************************************************************************/
/* ENTITY PROPERTIES */
/****************************************************************************************/
/**
* Gets the entities with the specified classname on the map.
*
* @param s_Classname The classname to check.
*
* @return An array containing the found entities.
*/
Handle:GetEntitiesWithClassname(String:s_Classname[]) {
// Start with the first entity (always -1)
new i_Current = -1;
// Create an array to store the results in
new Handle:h_Entities = CreateArray();
// Loop until all entities were found
while((i_Current = FindEntityByClassname(i_Current, s_Classname)) != -1) {
// Check if it is a valid entity
if(IsValidEntity(i_Current)) {
// Add the entity to the array
PushArrayCell(h_Entities, i_Current);
}
}
// Return the results
return h_Entities;
}
/**
* Gets the absolute position of the entity.
*
* @param i_Entity The entity to check.
*
* @return The position of the entity.
*/
Float:GetEntityAbsolutePosition(i_Entity) {
// Required buffers
decl Float:f_EntityPosition[3];
// Get the position
GetEntPropVector(i_Entity, Prop_Send, "m_vecOrigin", f_EntityPosition);
// Return the position
return f_EntityPosition;
}
/****************************************************************************************/
/* CLIENT PROPERTIES */
/****************************************************************************************/
/**
* Checks if the client has the specified model.
*
* @param i_Client The client to check.
* @param s_ModelFile The path to the model file to check.
*
* @return A boolean whether the client has the specified model.
*/
bool:ClientHasModel(i_Client, String:s_ModelFile[]) {
// Create the buffer for the model name
decl String:s_ClientModel[PLATFORM_MAX_PATH];
// Get the model and store it in the buffer
GetClientModel(i_Client, s_ClientModel, sizeof(s_ClientModel));
// Return whether the client has the specified model
return StrEqual(s_ClientModel, s_ModelFile);
}
/**
* Checks if the client has any weapon in the specified slot.
*
* @param i_Client The client to check.
* @param i_WeaponSlot The slot to check.
*
* @return A boolean whether the slot has a weapon in it.
*/
bool:ClientHasWeaponInSlot(i_Client, i_WeaponSlot) {
return GetPlayerWeaponSlot(i_Client, i_WeaponSlot) != -1;
}
/**
* Checks if the client is being revived.
*
* @param i_Client The client to check.
*
* @return A boolean whether the client is being revived.
*/
bool:ClientIsBeingRevived(i_Client) {
// Check if the client has someone that is reviving them
return GetEntProp(i_Client, Prop_Send, "m_reviveOwner", 1) > 0;
}
/**
* Checks if the client is incapacitated.
*
* @param i_Client The client to check.
*
* @return A boolean whether the client is incapacitated.
*/
bool:ClientIsIncapacitated(i_Client) {
// Check if the client is incapacitated
return GetEntProp(i_Client, Prop_Send, "m_isIncapacitated", 1) > 0;
}
/**
* Gets the name of the weapon in the specified slot.
*
* @param i_Client The client to check.
* @param i_WeaponSlot The weapon slot to check.
*
* @return A string with the weapon name.
*/
String:GetClientWeaponSlotWeaponName(i_Client, i_WeaponSlot) {
// Get the weapon's entity index
new i_Weapon = GetPlayerWeaponSlot(i_Client, i_WeaponSlot);
// Create a buffer for the classname
decl String:s_WeaponClassname[PLATFORM_MAX_PATH];
// Get the weapon's classname
GetEntityClassname(i_Weapon, s_WeaponClassname, sizeof(s_WeaponClassname));
// Return the name
return s_WeaponClassname;
}
/****************************************************************************************/
/* RAY TRACING */
/****************************************************************************************/
/**
* Checks if the target position is visible from the origin position.
*
* @param f_Origin The origin position.
* @param f_Target The target position.
*
* @return A boolean whether the target position is visible.
*/
bool:OriginVisibleToTarget(Float:f_Origin[3], Float:f_Target[3]) {
// Create the required buffers
decl Float:f_RelativePosition[3], Float:f_Angles[3], Float:f_TraceStart[3];
// Compute the vector from the origin to the target
MakeVectorFromPoints(f_Origin, f_Target, f_RelativePosition);
// Get the angle from the vector calculated above
GetVectorAngles(f_RelativePosition, f_Angles);
// Execute the actual ray trace
new Handle:h_Trace = TR_TraceRayFilterEx(f_Origin, f_Angles, MASK_ALL, RayType_Infinite, TraceFilter);
// Check if the trace hit the target
new bool:b_EntityVisible = false;
if(TR_DidHit(h_Trace)) {
// Retrieve the position where the trace ended
TR_GetEndPosition(f_TraceStart, h_Trace);
// If the length of the ray plus angle tolerance is equal to or bigger than the absolute distance from origin to target, the trace hit the target
b_EntityVisible = GetVectorDistance(f_Origin, f_TraceStart, false) + 25 >= GetVectorDistance(f_Origin, f_Target);
}
// Close the trace handle
CloseHandle(h_Trace);
// Return the result
return b_EntityVisible;
}
/**
* Filter used to determine if the ray trace has hit something.
*
* @param i_Entity The entity to check for collision.
*
* @return A boolean whether the ray trace should stop or not.
*/
bool:TraceFilter(i_Entity) {
// Don't hit WORLD, or invalid entities
return i_Entity && i_Entity > MaxClients && IsValidEntity(i_Entity);
}
/****************************************************************************************/
/* MISCELLANEOUS FUNCTIONS */
/****************************************************************************************/
/**
* Gets some random angles.
*
* @return A Float[3] with random angles.
*/
Float:GetRandomAngles() {
// Required buffers
decl Float:f_Angles[3];
// Generate random angles
f_Angles[0] = GetRandomFloat(-180.0, 180.0);
f_Angles[1] = GetRandomFloat(-180.0, 180.0);
f_Angles[2] = GetRandomFloat(-180.0, 180.0);
// Return the float
return f_Angles;
}
The errors:
Code:
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(290) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(293) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(308) : error 008: must be a constant expression; assumed zero
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(311) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(323) : error 008: must be a constant expression; assumed zero
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(326) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(335) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(335) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(335) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(345) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(348) : error 008: must be a constant expression; assumed zero
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(354) : error 017: undefined symbol "i_HordeEntityDistance"
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(364) : error 001: expected token: ")", but found "{"
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(367) : error 001: expected token: ")", but found "{"
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(379) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(382) : error 008: must be a constant expression; assumed zero
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(388) : warning 213: tag mismatch
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(401) : error 001: expected token: ")", but found "{"
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(432) : error 017: undefined symbol "s_CoachMolotov"
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(432) : error 029: invalid expression, assumed zero
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(432) : error 029: invalid expression, assumed zero
/home/groups/sourcemod/upload_tmp/php66fZtJ.sp(432) : fatal error 187: too many error messages on one line
Thanks in advance!
Last edited by Qub1; 03-04-2015 at 20:05.
|
|