Junior Member
|
01-15-2023
, 01:22
Plugin Code Help (RXG Mines) - Deathmsg
|
#1
|
Hi All,
I`m super new to playing with scripting and learning as I go here. I am currently using the Rxg_Mines plugin to play with and understand a bit of how everything works while reading and learning what everything does.
One of my issues is that I am looking to change the Death Message that pops up on the top right of the players screen when they die from the mine exploding on them. It currently shows "Player name" "Skull" "Player Name". What I am looing to do is change it from the skull to a different image which I believe is "Shieldgun"
If I am on the right path (Please let me know), here is where I believe the code would be changed
Code:
if( detonate ) {
decl String:targetname[64];
GetEntPropString( caller, Prop_Data, "m_iName", targetname, sizeof(targetname) );
decl String:buffers[2][32];
ExplodeString( targetname, "_", buffers, 2, 32 );
new ent_mine = StringToInt( buffers[1] );
AcceptEntityInput( ent_mine, "break" );
}
return;
I tried to make changes to the "ExplodeString" but all else just breaks it so the mines are not broken.
Here is the full code of the Rxg_Mines script
Code:
/* /////////////////////////////////
// ______________ ___________
// \______ \ \/ / _____/
// | _/\ / \ ___
// | | \/ \ \_\ \
// |____|_ /___/\ \______ /
// \/ \_/ \/
// R E F L E X - G A M E R S
*/
#include <sourcemod>
#include <sdktools>
#pragma semicolon 1
//
// Changelog:
// 11:48 PM 11/30/2012 - 1.0.4
// default mines to 3
// team filtering option
// finer laser texture (less aliasing)
// 1:23 PM 10/30/2012 - 1.0.3beta
// silent defusal
// reduced defuse time (3->2 seconds)
// 5:29 PM 10/29/2012 - 1.0.2beta
// mine defusal
// 10:37 PM 10/28/2012 - 1.0.1beta
// reduced explosion sound volume
// throttled explosion sounds (1 per 0.1 seconds)
// proper explosion sound panning
// placement on windows
// 4:12 PM 10/27/2012 - 1.0.0beta
// initial release
//----------------------------------------------------------------------------------------------------------------------
#define SOUND_PLACE "npc/roller/blade_cut.wav"
#define SOUND_ARMING "npc/roller/mine/rmine_blades_in2.wav" // UI/beep07.wav
#define SOUND_ARMED "items/nvg_on.wav"
#define SOUND_DEFUSE "weapons/c4/c4_disarm.wav"
//----------------------------------------------------------------------------------------------------------------------
#define MODEL_MINE "models/tripmine/tripmine.mdl"
#define MODEL_BEAM "materials/sprites/purplelaser1.vmt"
#define LASER_WIDTH 6.0//12.0
//#define LASER_COLOR_T "254 218 92"
//#define LASER_COLOR_T "128 109 46"
//#define LASER_COLOR_T "104 167 72"
//#define LASER_COLOR_CT "38 75 251"
//#define LASER_COLOR_D "38 251 42"
#define LASER_COLOR_T "255 0 0"
#define LASER_COLOR_CT "0 0 255"
#define LASER_COLOR_D "38 251 42"
//----------------------------------------------------------------------------------------------------------------------
//
// the distances for the placement traceray from the client's eyes
//
#define TRACE_START 1.0
#define TRACE_LENGTH 80.0
//----------------------------------------------------------------------------------------------------------------------
#define COMMAND "mine"
#define ALTCOMMAND "buyammo2"
//----------------------------------------------------------------------------------------------------------------------
public Plugin:myinfo = {
name = "rxg_mines",
author = "REFLEX-GAMERS",
description = "CS:GO trip mines",
version = "1.0.4",
url = "www.reflex-gamers.com"
};
//----------------------------------------------------------------------------------------------------------------------
new Handle:sm_pp_tripmines; // number of mines each player gets per round
new Handle:sm_pp_minedmg; // damage of the mines
new Handle:sm_pp_minerad; // radius override for explosion (0=disable)
new Handle:sm_pp_minefilter; // detonation mode
#define sm_pp_tripmines_desc "Number of mines each player gets per round"
new num_mines[MAXPLAYERS+1]; // number of mines per player
new mine_counter = 0;
new bool:explosion_sound_enable=true;
//new last_playeruse_id;
//new last_playeruse_target;
new last_mine_used;
new defuse_time[MAXPLAYERS+1];
new defuse_target[MAXPLAYERS+1];
new Float:defuse_position[MAXPLAYERS+1][3];
new Float:defuse_angles[MAXPLAYERS+1][3];
new bool:defuse_cancelled[MAXPLAYERS+1];
new defuse_userid[MAXPLAYERS+1];
#define DEFUSE_ANGLE_THRESHOLD 5.0 // 5 degrees
#define DEFUSE_POSITION_THRESHOLD 1.0 // 1 unit
new minefilter;
//new g_test = -1;
//----------------------------------------------------------------------------------------------------------------------
public OnPluginStart() {
sm_pp_tripmines = CreateConVar( "sm_pp_tripmines", "10", sm_pp_tripmines_desc, FCVAR_PLUGIN );
sm_pp_minedmg = CreateConVar( "sm_pp_minedmg", "200", "damage (magnitude) of the tripmines", FCVAR_PLUGIN );
sm_pp_minerad = CreateConVar( "sm_pp_minerad", "200", "override for explosion damage radius", FCVAR_PLUGIN );
sm_pp_minefilter = CreateConVar( "sm_pp_minefilter", "2", "0 = detonate when laser touches anyone, 1 = enemies and owner only, 2 = enemies only", FCVAR_PLUGIN );
HookEvent( "round_start", Event_RoundStart );
HookEvent( "player_use", Event_PlayerUse );
HookConVarChange( sm_pp_tripmines, CVarChanged_tripmines );
HookConVarChange( sm_pp_minefilter, CVarChanged_minefilter );
RegConsoleCmd( COMMAND, Command_Mine );
if( strlen( ALTCOMMAND ) != 0 ) {
RegConsoleCmd( ALTCOMMAND, Command_Mine );
}
minefilter = GetConVarInt( sm_pp_minefilter );
}
//----------------------------------------------------------------------------------------------------------------------
//
// precache models and sounds during map load
//
public OnMapStart() {
// PRECACHE SOUNDS
PrecacheSound( SOUND_PLACE, true );
PrecacheSound( SOUND_ARMING, true );
PrecacheSound( SOUND_ARMED, true );
PrecacheSound( SOUND_DEFUSE, true );
// PRECACHE MODELS
PrecacheModel( MODEL_MINE );
PrecacheModel( MODEL_BEAM, true );
AddFileToDownloadsTable( "models/tripmine/tripmine.dx90.vtx" );
AddFileToDownloadsTable( "models/tripmine/tripmine.mdl" );
AddFileToDownloadsTable( "models/tripmine/tripmine.phy" );
AddFileToDownloadsTable( "models/tripmine/tripmine.vvd" );
AddFileToDownloadsTable( "materials/models/tripmine/minetexture.vmt" );
AddFileToDownloadsTable( "materials/models/tripmine/minetexture.vtf" );
PrecacheSound( "weapons/hegrenade/explode3.wav" );
PrecacheSound( "weapons/hegrenade/explode4.wav" );
PrecacheSound( "weapons/hegrenade/explode5.wav" );
}
//----------------------------------------------------------------------------------------------------------------------
bool:IsValidClient( client ) {
return (client > 0 && client <= MaxClients && IsClientInGame(client));
}
//----------------------------------------------------------------------------------------------------------------------
//
// sm_pp_tripmines cvar changed, clamp player mines
//
public CVarChanged_tripmines( Handle:cvar, const String:oldval[], const String:newval[] ) {
if( strcmp( oldval, newval ) == 0 ) return;
ClampMines();
}
public CVarChanged_minefilter( Handle:cvar, const String:oldval[], const String:newval[] ) {
if( strcmp( oldval, newval ) == 0 ) return;
minefilter = GetConVarInt( sm_pp_minefilter );
}
//----------------------------------------------------------------------------------------------------------------------
//
// restore mines on round start
//
public Event_RoundStart( Handle:event, const String:name[], bool:dontBroadcast ) {
GiveAllPlayersMines();
mine_counter = 0;
explosion_sound_enable=true;
}
//----------------------------------------------------------------------------------------------------------------------
//
// give player his mines on connect
//
public OnClientConnected( client ) {
GivePlayerMines( client );
}
//----------------------------------------------------------------------------------------------------------------------
public OnClientDisconnect( client ) {
DeletePlacedMines( client );
}
//----------------------------------------------------------------------------------------------------------------------
public DeletePlacedMines(client) {
new ent = -1;
decl String:name[32];
while( (ent = FindEntityByClassname( ent, "prop_physics_override" )) != -1 ) {
GetEntPropString( ent, Prop_Data, "m_iName", name, 32 );
if( strncmp( name, "rxgtripmine", 11, true ) == 0 ) {
if( GetEntPropEnt( ent, Prop_Data, "m_hLastAttacker" ) == client ) { // slight hack here, cant use owner entity because it wont allow the owner to destroy his own mines.
AcceptEntityInput( ent, "Kill" );
}
}
}
while( (ent = FindEntityByClassname( ent, "env_beam" )) != -1 ) {
GetEntPropString( ent, Prop_Data, "m_iName", name, 32 );
if( strncmp( name, "rxgtripmine", 11, true ) == 0 ) {
if( GetEntPropEnt( ent, Prop_Data, "m_hOwnerEntity" ) == client ) {
AcceptEntityInput( ent, "Kill" );
}
}
}
}
//----------------------------------------------------------------------------------------------------------------------
//
// give all players their mines
//
public GiveAllPlayersMines() {
new mines = GetConVarInt( sm_pp_tripmines );
for( new i = 0; i < MAXPLAYERS+1; i++ ) {
num_mines[i] = mines;
}
}
//----------------------------------------------------------------------------------------------------------------------
//
// give one player his mines
//
public GivePlayerMines( client ) {
new mines = GetConVarInt( sm_pp_tripmines );
num_mines[client] = mines;
}
//----------------------------------------------------------------------------------------------------------------------
//
// clamp all mines to the tripmine setting, used after the cvar is changed
//
public ClampMines() {
new mines = GetConVarInt( sm_pp_tripmines );
for( new i = 0; i < MAXPLAYERS+1; i++ ) {
if( num_mines[i] > mines ) {
num_mines[i] = mines;
}
}
}
//----------------------------------------------------------------------------------------------------------------------
public Action:Command_Mine( client, args ) {
if( IsClientConnected(client) ) {
if( IsPlayerAlive(client) ) {
if( num_mines[client] > 0 ) {
// plant mine
PlaceMine(client);
} else {
if( GetConVarInt( sm_pp_tripmines ) != 0 ) {
PrintCenterText( client, "You have no more mines." );
} else {
PrintCenterText( client, "Mines are disabled." );
}
}
}
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------------------------
public PlaceMine( client ) {
decl Float:trace_start[3], Float:trace_angle[3], Float:trace_end[3], Float:trace_normal[3];
GetClientEyePosition( client, trace_start );
GetClientEyeAngles( client, trace_angle );
GetAngleVectors( trace_angle, trace_end, NULL_VECTOR, NULL_VECTOR );
NormalizeVector( trace_end, trace_end ); // end = normal
// offset start by near point
for( new i = 0; i < 3; i++ )
trace_start[i] += trace_end[i] * TRACE_START;
for( new i = 0; i < 3; i++ )
trace_end[i] = trace_start[i] + trace_end[i] * TRACE_LENGTH;
TR_TraceRayFilter( trace_start, trace_end, CONTENTS_SOLID|CONTENTS_WINDOW, RayType_EndPoint, TraceFilter_All, 0 );
if( TR_DidHit( INVALID_HANDLE ) ) {
num_mines[client]--;
if( num_mines[client] != 0 ) {
PrintCenterText( client, "You have %d mines left!", num_mines[client] );
} else {
PrintCenterText( client, "That was your last mine!" );
}
TR_GetEndPosition( trace_end, INVALID_HANDLE );
TR_GetPlaneNormal(INVALID_HANDLE, trace_normal);
SetupMine( client, trace_end, trace_normal );
} else {
PrintCenterText( client, "Invalid mine position." );
}
}
//----------------------------------------------------------------------------------------------------------------------
//
// filter out mine placement on anything but the map
//
public bool:TraceFilter_All( entity, contentsMask ) {
return false;
}
//----------------------------------------------------------------------------------------------------------------------
public MineLaser_OnTouch( const String:output[], caller, activator, Float:delay ) {
AcceptEntityInput(caller, "TurnOff");
AcceptEntityInput(caller, "TurnOn");
if( !IsValidClient(activator) ) return;
if( !IsPlayerAlive(activator) ) return;
new bool:detonate = false;
if( minefilter == 1 || minefilter == 2 ) {
// detonate if enemy or owner
new owner = GetEntPropEnt( caller, Prop_Data, "m_hOwnerEntity" );
if( !IsValidClient(owner) ) {
// something went wrong, bypass test
detonate = true;
} else {
new team = GetClientTeam( owner );
if( GetClientTeam( activator ) != team || (owner == activator && minefilter == 1) ) {
detonate = true;
}
}
} else if( minefilter == 0 ) {
// detonate always
detonate = true;
}
if( detonate ) {
decl String:targetname[64];
GetEntPropString( caller, Prop_Data, "m_iName", targetname, sizeof(targetname) );
decl String:buffers[2][32];
ExplodeString( targetname, "_", buffers, 2, 32 );
new ent_mine = StringToInt( buffers[1] );
AcceptEntityInput( ent_mine, "break" );
}
return;
}
//----------------------------------------------------------------------------------------------------------------------
public SetupMine( client, Float:position[3], Float:normal[3] ) {
decl String:mine_name[64];
decl String:beam_name[64];
decl String:str[128];
Format( mine_name, 64, "rxgtripmine%d", mine_counter );
new Float:angles[3];
GetVectorAngles( normal, angles );
new ent = CreateEntityByName( "prop_physics_override" );
Format( beam_name, 64, "rxgtripmine%d_%d", mine_counter, ent );
DispatchKeyValue( ent, "model", MODEL_MINE );
DispatchKeyValue( ent, "physdamagescale", "0.0"); // enable this to destroy via physics?
DispatchKeyValue( ent, "health", "1" ); // use the set entity health function instead ?
DispatchKeyValue( ent, "targetname", mine_name);
DispatchKeyValue( ent, "spawnflags", "256"); // set "usable" flag
DispatchSpawn( ent );
SetEntityMoveType(ent, MOVETYPE_NONE);
SetEntProp(ent, Prop_Data, "m_takedamage", 2);
SetEntPropEnt(ent, Prop_Data, "m_hLastAttacker", client); // use this to identify the owner (see below)
//SetEntPropEnt(ent, Prop_Data, "m_hOwnerEntity",client); //Set the owner of the mine (cant, it stops the owner from destroying it)
SetEntityRenderColor( ent, 255, 255, 255, 255 );
SetEntProp( ent, Prop_Send, "m_CollisionGroup", 2); // set non-collidable
// when the mine is broken, delete the laser beam
Format( str, sizeof(str), "%s,Kill,,0,-1", beam_name );
DispatchKeyValue( ent, "OnBreak", str );
// hook to explosion function
HookSingleEntityOutput( ent, "OnBreak", MineBreak, true );
HookSingleEntityOutput( ent, "OnPlayerUse", MineUsed, false );
// offset placement slightly so it is on the wall's surface
for( new i =0 ; i < 3; i++ ) {
position[i] += normal[i] * 0.5;
}
TeleportEntity(ent, position, angles, NULL_VECTOR );//angles, NULL_VECTOR );
// trace ray for laser (allow passage through windows)
TR_TraceRayFilter(position, angles, CONTENTS_SOLID, RayType_Infinite, TraceFilter_All, 0);
new Float:beamend[3];
TR_GetEndPosition( beamend, INVALID_HANDLE );
// create beam
new ent_laser = CreateLaser( beamend, position, beam_name, GetClientTeam(client) );
// when touched, activate/break the mine
if( minefilter == 1 || minefilter == 2 ) {
HookSingleEntityOutput( ent_laser, "OnTouchedByEntity", MineLaser_OnTouch );
} else {
// detonate against anything
Format( str, sizeof(str), "%s,Break,,0,-1", mine_name );
DispatchKeyValue( ent_laser, "OnTouchedByEntity", str );
}
SetEntPropEnt(ent_laser, Prop_Data, "m_hOwnerEntity",client); //Set the owner of the mine's beam
// timer for activating
new Handle:data;
CreateDataTimer( 1.0, ActivateTimer, data, TIMER_REPEAT );
ResetPack(data);
WritePackCell(data, 0);
WritePackCell(data, ent);
WritePackCell(data, ent_laser);
PlayMineSound( ent, SOUND_PLACE );
mine_counter++;
}
//----------------------------------------------------------------------------------------------------------------------
public Action:ActivateTimer( Handle:timer, Handle:data ) {
ResetPack(data);
new counter = ReadPackCell(data);
new ent = ReadPackCell(data);
new ent_laser = ReadPackCell(data);
if( !IsValidEntity(ent) ) { // mine was broken (gunshot/grenade) before it was armed
return Plugin_Stop;
}
if( counter < 1 ) {
PlayMineSound( ent, SOUND_ARMING );
counter++;
ResetPack(data);
WritePackCell(data, counter);
} else {
PlayMineSound( ent, SOUND_ARMED );
// enable touch trigger and increase brightness
DispatchKeyValue(ent_laser, "TouchType", "4");
DispatchKeyValue(ent_laser, "renderamt", "220");
return Plugin_Stop;
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------------------------
PlayMineSound( entity, const String:sound[] ) {
EmitSoundToAll( sound, entity );
}
//----------------------------------------------------------------------------------------------------------------------
public MineBreak (const String:output[], caller, activator, Float:delay)
{
new Float:pos[3];
GetEntPropVector(caller, Prop_Send, "m_vecOrigin", pos);
// create explosion
CreateExplosionDelayed( pos, GetEntPropEnt( caller, Prop_Data, "m_hLastAttacker" ) );
}
//----------------------------------------------------------------------------------------------------------------------
public Action:DefuseTimer( Handle:timer, any:client ) {
new userid = defuse_userid[client];
new old_client = GetClientOfUserId( userid );
if( !IsValidClient(old_client) || old_client != client ) {
return Plugin_Stop; // something went wrong
}
if( defuse_cancelled[client] ) {
defuse_userid[client] = 0;
return Plugin_Stop;
}
if( !IsValidEntity(defuse_target[client]) ) {
// mine was killed
defuse_userid[client] = 0;
return Plugin_Stop;
}
new bool:player_moved=false;
// VERIFY ANGLES
new Float:angles[3];
GetClientEyeAngles( client, angles );
for( new i = 0; i < 3; i++ ) {
if( FloatAbs(angles[i] - defuse_angles[client][i]) > DEFUSE_ANGLE_THRESHOLD ) {
player_moved=true;
break;
}
}
if( !player_moved ) {
new Float:pos[3];
GetClientAbsOrigin( client, pos );
for( new i = 0; i < 3; i++ ) {
pos[i] -= defuse_position[client][i];
pos[i] *= pos[i];
}
new Float:dist = pos[0] + pos[1] + pos[2];
if( dist >= (DEFUSE_POSITION_THRESHOLD*DEFUSE_POSITION_THRESHOLD) ) {
player_moved = true;
}
}
if( player_moved ) {
PrintHintText( client, "Defusal Interrupted." );
defuse_userid[client] = 0;
return Plugin_Stop;
}
defuse_time[client]++;
if( defuse_time[client] < 2 ) {
new String:message[16] = "Defusing.";
for( new i = 0; i < defuse_time[client]; i++ )
StrCat( message, 16, "." );
PrintHintText( client, message );
} else {
EmitSoundToClient( client, SOUND_PLACE );//
// PlayMineSound( defuse_target[client], SOUND_PLACE );
num_mines[client]++;
// defuse mine and give to player
UnhookSingleEntityOutput( defuse_target[client], "OnBreak", MineBreak );
AcceptEntityInput( defuse_target[client], "Break" );
PrintHintText( client, "Mine Defused. You have %d mine%s now", num_mines[client], num_mines[client] != 1 ? "s" : "" );
defuse_userid[client] = 0;
return Plugin_Stop;
}
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------------------------
StartDefusal( client, target ) {
if( defuse_userid[client] != 0 ) return; // defusal already in progress
PrintHintText( client, "Defusing." );
defuse_time[client] = 0;
defuse_target[client] = target;
GetClientAbsOrigin( client, defuse_position[client] );
GetClientEyeAngles( client, defuse_angles[client] );
defuse_cancelled[client] = false;
defuse_userid[client] = GetClientUserId(client);
CreateTimer( 1.0, DefuseTimer, client, TIMER_REPEAT );
EmitSoundToClient( client, SOUND_DEFUSE );//
// PlayMineSound( defuse_target[client], SOUND_DEFUSE );
}
//----------------------------------------------------------------------------------------------------------------------
public Action:OnPlayerRunCmd( client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon ) {
if( !IsValidClient(client) ) return Plugin_Continue;
if( (buttons & IN_USE) == 0 ) {
if( defuse_userid[client] && !defuse_cancelled[client] ) { // is defuse in progress?
defuse_cancelled[client] = true;
PrintHintText( client, "Defusal Cancelled." );
}
}
return Plugin_Continue;
}
//----------------------------------------------------------------------------------------------------------------------
public MineUsed(const String:output[], caller, activator, Float:delay)
{
// register last mine touched
last_mine_used = caller;
// PrintToChatAll( "debug1, %s, %d, %d, %d", output, caller, last_playeruse_id, last_playeruse_target );
}
//----------------------------------------------------------------------------------------------------------------------
public Event_PlayerUse( Handle:event, const String:name[], bool:dontBroadcast ) {
new id = GetEventInt( event, "userid" );
new target = GetEventInt( event, "entity" );
if( last_mine_used == target ) { // verify this use event matches with the mine-use event
new client = GetClientOfUserId( id );
if( client == 0 ) return; // client has disconnected
StartDefusal( client, target );
}
}
//----------------------------------------------------------------------------------------------------------------------
public CreateLaser(Float:start[3], Float:end[3], String:name[], team)
{
new ent = CreateEntityByName("env_beam");
if (ent != -1)
{
decl String:color[16];
if( team == 2 ) color = LASER_COLOR_T;
else if( team == 3 ) color = LASER_COLOR_CT;
else color = LASER_COLOR_D;
TeleportEntity(ent, start, NULL_VECTOR, NULL_VECTOR);
SetEntityModel(ent, MODEL_BEAM); // This is where you would put the texture, ie "sprites/laser.vmt" or whatever.
SetEntPropVector(ent, Prop_Data, "m_vecEndPos", end);
DispatchKeyValue(ent, "targetname", name );
DispatchKeyValue(ent, "rendercolor", color );
DispatchKeyValue(ent, "renderamt", "80");
DispatchKeyValue(ent, "decalname", "Bigshot");
DispatchKeyValue(ent, "life", "0");
DispatchKeyValue(ent, "TouchType", "0");
DispatchSpawn(ent);
SetEntPropFloat(ent, Prop_Data, "m_fWidth", LASER_WIDTH);
SetEntPropFloat(ent, Prop_Data, "m_fEndWidth", LASER_WIDTH);
ActivateEntity(ent);
AcceptEntityInput(ent, "TurnOn");
}
return ent;
}
//----------------------------------------------------------------------------------------------------------------------
public CreateExplosionDelayed( Float:vec[3], owner ) {
new Handle:data;
CreateDataTimer( 0.1, CreateExplosionDelayedTimer, data );
WritePackCell(data,owner);
WritePackFloat(data,vec[0]);
WritePackFloat(data,vec[1]);
WritePackFloat(data,vec[2]);
}
//----------------------------------------------------------------------------------------------------------------------
public Action:CreateExplosionDelayedTimer( Handle:timer, Handle:data ) {
ResetPack(data);
new owner = ReadPackCell(data);
new Float:vec[3];
vec[0] = ReadPackFloat(data);
vec[1] = ReadPackFloat(data);
vec[2] = ReadPackFloat(data);
CreateExplosion( vec, owner );
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------------------------
public Action:EnableExplosionSound( Handle:timer ) {
explosion_sound_enable = true;
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------------------------
public CreateExplosion( Float:vec[3], owner ) {
new ent = CreateEntityByName("env_explosion");
DispatchKeyValue(ent, "classname", "env_explosion");
SetEntPropEnt(ent, Prop_Data, "m_hOwnerEntity",owner); //Set the owner of the explosion
new mag = GetConVarInt( sm_pp_minedmg );
new rad = GetConVarInt( sm_pp_minerad );
SetEntProp(ent, Prop_Data, "m_iMagnitude",mag);
if( rad != 0 ) {
SetEntProp(ent, Prop_Data, "m_iRadiusOverride",rad);
}
DispatchSpawn(ent);
ActivateEntity(ent);
decl String:exp_sample[64];
Format( exp_sample, 64, ")weapons/hegrenade/explode%d.wav", GetRandomInt( 3, 5 ) );
if( explosion_sound_enable ) {
explosion_sound_enable = false;
EmitAmbientSound( exp_sample, vec, _, SNDLEVEL_GUNFIRE );
CreateTimer( 0.1, EnableExplosionSound );
}
TeleportEntity(ent, vec, NULL_VECTOR, NULL_VECTOR);
AcceptEntityInput(ent, "explode");
AcceptEntityInput(ent, "kill");
}
Here is a snippit of code that gave me the thought
Code:
public Action:OnPlayerDeath_Pre(Handle:event, const String:name[], bool:dontBroadcast)
{
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
if (1 <= attacker <= MaxClients)
{
decl String:g_szWeapon[32];
GetEventString(event, "weapon", g_szWeapon, sizeof(g_szWeapon));
if (StrEqual(g_szWeapon, "env_beam"))
{
SetEventString(event, "weapon", "shieldgun");
}
}
return Plugin_Continue;
}
and its full code from the plugin
Code:
#pragma semicolon 1
/*
I N C L U D E S
------------------------------------------------
*/
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <lasermines>
/*
------------------------------------------------
*/
/*
D E F I N E S
------------------------------------------------
*/
#define PLUGIN_VERSION "1.4.2"
#define MDL_LASER "sprites/laser.vmt"
#define MDL_MINE "models/tripmine/tripmine.mdl"
#define SND_MINEPUT "npc/roller/blade_cut.wav"
#define SND_MINEACT "npc/roller/mine/rmine_blades_in2.wav"
#define SND_BUYMINE "items/itempickup.wav"
#define SND_CANTBUY "buttons/weapon_cant_buy.wav"
/*
------------------------------------------------
*/
/*
|G| |L| |O| |B| |A| |L| |S|
------------------------------------------------
*/
new Handle:h_enable, bool:b_enable,
Handle:h_amount, i_amount,
Handle:h_maxamount, i_maxamount,
Handle:h_damage, i_damage,
Handle:h_explode_damage, i_explode_damage,
Handle:h_explode_radius, i_explode_radius,
Handle:h_health, i_health,
Handle:h_color_t, String:s_color_t[16],
Handle:h_color_ct, String:s_color_ct[16],
Handle:h_activate_time, Float:f_activate_time,
Handle:h_use_buy_mode, bool:b_use_buy_mode,
Handle:h_should_buy_zone, bool:b_should_buy_zone,
Handle:h_allow_pickup, bool:b_allow_pickup,
Handle:h_allow_friendly_pickup, bool:b_allow_friendly_pickup,
Handle:h_allow_enemy_pickup, bool:b_allow_enemy_pickup,
Handle:h_price, i_price;
new Handle:h_friendlyfire, bool:b_friendlyfire;
/*
F O R W A R D S
------------------------------------------------
*/
new Handle:h_fwdOnPlantLasermine,
Handle:h_fwdOnLaserminePlanted,
Handle:h_fwdOnPreHitByLasermine,
Handle:h_fwdOnPostHitByLasermine,
Handle:h_fwdOnPreBuyLasermine,
Handle:h_fwdOnPostBuyLasermine,
Handle:h_fwdOnPrePickupLasermine,
Handle:h_fwdOnPostPickupLasermine;
/*
------------------------------------------------
*/
new i_clients_amount[MAXPLAYERS+1],
i_clients_myamount[MAXPLAYERS+1],
i_clients_maxlimit[MAXPLAYERS+1],
b_used_by_native[MAXPLAYERS+1],
i_buy_limit[MAXPLAYERS+1];
new gInBuyZone = -1;
new gAccount = -1;
/*
P L U G I N I N F O
------------------------------------------------
*/
public Plugin:myinfo =
{
name = "Lasermines",
author = "FrozDark (HLModders.ru LLC)",
description = "Plants a laser mine",
version = PLUGIN_VERSION,
url = "http://www.hlmod.ru/"
};
new bool:b_late;
/*
Fires when the plugin is asked to be loaded
-------------------------------------------------------
*/
public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
CreateNative("AddClientLasermines", Native_AddMines);
CreateNative("SetClientLasermines", Native_SetMines);
CreateNative("SubClientLasermines", Native_SubstractMines);
CreateNative("GetClientLasermines", Native_GetMines);
CreateNative("PlantClientLasermine", Native_PlantMine);
CreateNative("ClearMapClientLasermines", Native_ClearMapMines);
CreateNative("IsEntityLasermine", Native_IsLasermine);
CreateNative("GetClientByLasermine", Native_GetClientByLasermine);
CreateNative("SetClientMaxLasermines", Native_SetClientMaxLasermines);
CreateNative("ResetClientMaxLasermines", Native_ResetClientMaxLasermines);
CreateNative("GetBeamByLasermine", Native_GetBeamByLasermine);
CreateNative("GetLasermineByBeam", Native_GetLasermineByBeam);
h_fwdOnPlantLasermine = CreateGlobalForward("OnPlantLasermine", ET_Hook, Param_Cell, Param_FloatByRef, Param_CellByRef, Param_CellByRef, Param_CellByRef, Param_Array);
h_fwdOnLaserminePlanted = CreateGlobalForward("OnLaserminePlanted", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Cell, Param_Cell, Param_Cell, Param_Array);
h_fwdOnPreHitByLasermine = CreateGlobalForward("OnPreHitByLasermine", ET_Hook, Param_Cell, Param_CellByRef, Param_CellByRef, Param_CellByRef, Param_CellByRef);
h_fwdOnPostHitByLasermine = CreateGlobalForward("OnPostHitByLasermine", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell);
h_fwdOnPreBuyLasermine = CreateGlobalForward("OnPreBuyLasermine", ET_Hook, Param_Cell, Param_CellByRef, Param_CellByRef);
h_fwdOnPostBuyLasermine = CreateGlobalForward("OnPostBuyLasermine", ET_Ignore, Param_Cell, Param_Cell, Param_Cell);
h_fwdOnPrePickupLasermine = CreateGlobalForward("OnPrePickupLasermine", ET_Event, Param_Cell, Param_Cell, Param_Cell);
h_fwdOnPostPickupLasermine = CreateGlobalForward("OnPostPickupLasermine", ET_Ignore, Param_Cell, Param_Cell, Param_Cell);
RegPluginLibrary("lasermines");
b_late = late;
return APLRes_Success;
}
/*
Fires when the plugin starts
------------------------------------------------
*/
public OnPluginStart()
{
// Creates console variable version
CreateConVar("sm_lasermines_version", PLUGIN_VERSION, "The version of the plugin", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_CHEAT|FCVAR_DONTRECORD);
// Creates console variables
h_enable = CreateConVar( "sm_lasermines_enable", "1", "Enables/Disables the plugin", FCVAR_PLUGIN|FCVAR_NOTIFY, true, 0.0, true, 1.0);
h_amount = CreateConVar( "sm_lasermines_amount", "10", "The amount to give laser mines to a player each spawn (if buy mode is disabled, -1 = Infinity)", FCVAR_PLUGIN, true, -1.0);
h_maxamount = CreateConVar( "sm_lasermines_maxamount", "0", "The maximum amount of laser mines a player can carry. (0-Unlimited)", FCVAR_PLUGIN, true, 0.0);
h_damage = CreateConVar( "sm_lasermines_damage", "500", "The damage to deal to a player by the laser", FCVAR_PLUGIN, true, 1.0, true, 100000.0);
h_explode_damage = CreateConVar( "sm_lasermines_explode_damage", "100", "The damage to deal to a player when a laser mine breaks", FCVAR_PLUGIN, true, 0.0, true, 100000.0);
h_explode_radius = CreateConVar( "sm_lasermines_explode_radius", "300", "The radius of the explosion", FCVAR_PLUGIN, true, 1.0, true, 100000.0);
h_health = CreateConVar( "sm_lasermines_health", "1.0", "The laser mines health. 0 = never breaked", FCVAR_PLUGIN, true, 0.0, true, 100000.0);
h_activate_time = CreateConVar( "sm_lasermines_activatetime", "2", "The delay of laser mines' activation", FCVAR_PLUGIN, true, 0.0, true, 10.0);
h_use_buy_mode = CreateConVar( "sm_lasermines_buymode", "0", "Enables buy mode. In this mode you will have to buy mines", FCVAR_PLUGIN|FCVAR_NOTIFY, true, 0.0, true, 1.0);
h_should_buy_zone = CreateConVar( "sm_lasermines_buyzone", "0", "Whether a player have to stay in buy zone to buy mines", FCVAR_PLUGIN|FCVAR_NOTIFY, true, 0.0, true, 1.0);
h_price = CreateConVar( "sm_lasermines_price", "500", "The price of the laser mines", FCVAR_PLUGIN|FCVAR_NOTIFY, true, 0.0);
h_color_t = CreateConVar( "sm_lasermines_color_t", "255 0 0", "Terrorist's color. Set by RGB", FCVAR_PLUGIN);
h_color_ct = CreateConVar( "sm_lasermines_color_ct", "0 0 255", "Counter-Terrorist's color. Set by RGB", FCVAR_PLUGIN);
h_allow_pickup = CreateConVar( "sm_lasermines_allow_pickup", "1", "Allow players to pickup their planted lasermines", FCVAR_PLUGIN);
h_allow_friendly_pickup = CreateConVar( "sm_lasermines_allow_friendly_pickup", "1", "Allow players to pickup allies planted lasermines", FCVAR_PLUGIN);
h_allow_enemy_pickup = CreateConVar( "sm_lasermines_allow_enemy_pickup", "1", "Allow players to pickup enemys planted lasermines", FCVAR_PLUGIN);
h_friendlyfire = CreateConVar( "sm_friendlyfire", "2.0", "Friendly Fire Settings 0 = detonate when laser touches anyone, 1.0 = enemies and owner only, 2.0 = enemies only", FCVAR_PLUGIN );
// Gets them to the global
b_enable = GetConVarBool(h_enable);
i_amount = GetConVarInt(h_amount);
i_maxamount = GetConVarInt(h_maxamount);
i_damage = GetConVarInt(h_damage);
i_explode_damage = GetConVarInt(h_explode_damage);
i_explode_radius = GetConVarInt(h_explode_radius);
i_health = GetConVarInt(h_health);
f_activate_time = GetConVarFloat(h_activate_time);
b_use_buy_mode = GetConVarBool(h_use_buy_mode);
b_should_buy_zone = GetConVarBool(h_should_buy_zone);
i_price = GetConVarInt(h_price);
b_allow_pickup = GetConVarBool(h_allow_pickup);
b_allow_friendly_pickup = GetConVarBool(h_allow_friendly_pickup);
b_allow_enemy_pickup = GetConVarBool(h_allow_enemy_pickup);
b_friendlyfire = GetConVarBool(h_friendlyfire);
GetConVarString(h_color_t, s_color_t, sizeof(s_color_t));
GetConVarString(h_color_ct, s_color_ct, sizeof(s_color_ct));
b_friendlyfire = GetConVarBool(h_friendlyfire);
// Hooks their change
HookConVarChange(h_enable, OnConVarChanged);
HookConVarChange(h_amount, OnConVarChanged);
HookConVarChange(h_maxamount, OnConVarChanged);
HookConVarChange(h_damage, OnConVarChanged);
HookConVarChange(h_explode_damage, OnConVarChanged);
HookConVarChange(h_explode_radius, OnConVarChanged);
HookConVarChange(h_health, OnConVarChanged);
HookConVarChange(h_activate_time, OnConVarChanged);
HookConVarChange(h_use_buy_mode, OnConVarChanged);
HookConVarChange(h_should_buy_zone, OnConVarChanged);
HookConVarChange(h_price, OnConVarChanged);
HookConVarChange(h_color_t, OnConVarChanged);
HookConVarChange(h_color_ct, OnConVarChanged);
HookConVarChange(h_allow_pickup, OnConVarChanged);
HookConVarChange(h_allow_friendly_pickup, OnConVarChanged);
HookConVarChange(h_allow_enemy_pickup, OnConVarChanged);
HookConVarChange(h_friendlyfire, OnConVarChanged);
// Hooks event changes
HookEvent("player_spawn", OnPlayerSpawn);
HookEvent("player_death", OnPlayerDeath);
HookEvent("player_death", OnPlayerDeath_Pre, EventHookMode_Pre);
// Registers new console commands
RegConsoleCmd("sm_plantlm", Command_PlantMine, "Plant a laser mine");
RegConsoleCmd("sm_blm", Command_PlantMine, "Plant a laser mine");
RegConsoleCmd("sm_lm", Command_PlantMine, "Plant a laser mine");
RegConsoleCmd("sm_buylm", Command_BuyMines, "Buy laser mines");
RegConsoleCmd("sm_blm", Command_BuyMines, "Buy laser mines");
RegConsoleCmd("sm_bm", Command_BuyMines, "Buy laser mines");
// Hooks entity env_beam ouput events
HookEntityOutput("env_beam", "OnTouchedByEntity", OnTouchedByEntity);
// Loads the translation
LoadTranslations("lasermines.phrases");
// Finds offsets
if ((gInBuyZone = FindSendPropOffs("CCSPlayer", "m_bInBuyZone")) == -1)
SetFailState("Could not find offset \"m_bInBuyZone\"");
if ((gAccount = FindSendPropOffs("CCSPlayer", "m_iAccount")) == -1)
SetFailState("Could not find offset \"m_iAccount\"");
AutoExecConfig(true, "plugin.lasermines");
if (b_late)
{
b_late = false;
OnMapStart();
}
}
/*
------------------------------------------------
*/
/*
Cvars changes
------------------------------------------------
*/
public OnConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[])
{
if (convar == h_enable)
{
b_enable = bool:StringToInt(newValue);
}
else if (convar == h_amount)
{
i_amount = StringToInt(newValue);
LookupClients();
}
else if (convar == h_maxamount)
{
i_maxamount = StringToInt(newValue);
LookupClients();
}
else if (convar == h_damage)
{
i_damage = StringToInt(newValue);
}
else if (convar == h_explode_damage)
{
i_explode_damage = StringToInt(newValue);
}
else if (convar == h_explode_radius)
{
i_explode_radius = StringToInt(newValue);
}
else if (convar == h_health)
{
i_health = StringToInt(newValue);
}
else if (convar == h_activate_time)
{
f_activate_time = StringToFloat(newValue);
}
else if (convar == h_use_buy_mode)
{
b_use_buy_mode = bool:StringToInt(newValue);
}
else if (convar == h_should_buy_zone)
{
b_should_buy_zone = bool:StringToInt(newValue);
}
else if (convar == h_price)
{
i_price = StringToInt(newValue);
}
else if (convar == h_color_t)
{
strcopy(s_color_t, sizeof(s_color_t), newValue);
}
else if (convar == h_color_ct)
{
strcopy(s_color_ct, sizeof(s_color_ct), newValue);
}
else if (convar == h_friendlyfire)
{
b_friendlyfire = bool:StringToInt(newValue);
}
else if (convar == h_allow_pickup)
{
b_allow_pickup = bool:StringToInt(newValue);
}
else if (convar == h_allow_friendly_pickup)
{
b_allow_friendly_pickup = bool:StringToInt(newValue);
}
else if (convar == h_allow_enemy_pickup)
{
b_allow_enemy_pickup = bool:StringToInt(newValue);
}
}
LookupClients()
{
for (new i = 1; i <= MaxClients; i++)
{
OnClientConnected(i);
}
}
/*
Fires when the map starts
------------------------------------------------
*/
public OnMapStart()
{
PrecacheModel(MDL_MINE, true);
PrecacheModel(MDL_LASER, true);
PrecacheSound(SND_MINEPUT, true);
PrecacheSound(SND_MINEACT, true);
PrecacheSound(SND_BUYMINE, true);
PrecacheSound(SND_CANTBUY, true);
}
/*
------------------------------------------------
*/
public OnClientConnected(client)
{
if (!b_used_by_native[client])
{
i_clients_maxlimit[client] = i_maxamount;
i_clients_myamount[client] = i_amount;
}
}
/*
Fires when a client disconnects
------------------------------------------------
*/
public OnClientDisconnect(client)
{
i_buy_limit[client] = 0;
for (new index = MaxClients+1; index <= 2048; index++)
{
if (GetClientByLasermine(index) == client)
{
SDKUnhook(index, SDKHook_OnTakeDamage, OnTakeDamage);
AcceptEntityInput(index, "KillHierarchy");
}
}
}
/*
Fires when a client fully disconnected
------------------------------------------------
*/
public OnClientDisconnect_Post(client)
{
i_clients_amount[client] = 0;
b_used_by_native[client] = false;
}
/*
Touch event
------------------------------------------------
*/
public OnTouchedByEntity(const String:output[], caller, activator, Float:delay)
{
if (!(1 <= activator <= MaxClients))
{
return;
}
new owner = GetEntPropEnt(caller, Prop_Data, "m_hOwnerEntity");
new lasermine = GetLasermineByBeam(caller);
if (owner == -1 || lasermine == -1 || activator == owner || (!b_friendlyfire && GetClientTeam(activator) == GetClientTeam(owner)))
{
return;
}
decl dummy_caller, dummy_owner, damage, dummy_lasermine;
dummy_caller = caller;
dummy_owner = owner;
damage = i_damage;
dummy_lasermine = lasermine;
new Action:result = Forward_OnPreHit(activator, dummy_owner, dummy_caller, dummy_lasermine, damage);
switch (result)
{
case Plugin_Handled, Plugin_Stop :
{
return;
}
case Plugin_Continue :
{
dummy_caller = caller;
dummy_owner = owner;
damage = i_damage;
dummy_lasermine = lasermine;
}
}
// Make custom damage to the client
SDKHooks_TakeDamage(activator, dummy_caller, dummy_owner, float(damage), DMG_ENERGYBEAM);
Forward_OnPostHit(activator, dummy_owner, dummy_caller, dummy_lasermine, damage);
}
public OnPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if (!b_use_buy_mode)
{
i_clients_amount[client] = i_clients_myamount[client];
}
}
public OnPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
OnClientDisconnect(client);
}
public Action:OnPlayerDeath_Pre(Handle:event, const String:name[], bool:dontBroadcast)
{
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
if (1 <= attacker <= MaxClients)
{
decl String:g_szWeapon[32];
GetEventString(event, "weapon", g_szWeapon, sizeof(g_szWeapon));
if (StrEqual(g_szWeapon, "env_beam"))
{
SetEventString(event, "weapon", "shieldgun");
}
}
return Plugin_Continue;
}
/*
------------------------------------------------
*/
public Action:Command_BuyMines(client, argc)
{
// client = 0 or disabled or buy mode disabled or unlimited amount or client is not in game
if (!client || !b_enable || !b_use_buy_mode || i_clients_myamount[client] == -1 || !IsClientInGame(client))
{
return Plugin_Continue; // Stop trigger the command
}
// client is dead
if (!IsPlayerAlive(client))
{
PrintHintText(client, "%t", "Can't buy, while dead");
return Plugin_Handled; // Stop trigger the command
}
// client is spectator
if (GetClientTeam(client) <= 1)
{
PrintHintText(client, "%t", "Can't use, while spec");
return Plugin_Handled; // Stop trigger the command
}
// If buy zone mode is enabled and player is out of buy zone range
if (b_should_buy_zone && !bool:GetEntData(client, gInBuyZone, 1))
{
PrintHintText(client, "%t", "Out of buy zone");
return Plugin_Handled; // Stop trigger the command
}
new amount = 1;
if (argc)
{
decl String:txt[6];
GetCmdArg(1, txt, sizeof(txt));
amount = StringToInt(txt);
if (bool:i_clients_maxlimit[client])
{
if (amount > i_clients_maxlimit[client])
{
amount = i_clients_maxlimit[client];
}
else if (amount < 1)
{
amount = 1;
}
}
}
decl dummy_amount, cost, boughtamount;
dummy_amount = amount;
cost = i_price;
boughtamount = 0;
new Action:result = Forward_OnPreBuy(client, dummy_amount, cost);
switch (result)
{
case Plugin_Handled, Plugin_Stop :
{
return result;
}
case Plugin_Continue :
{
dummy_amount = amount;
cost = i_price;
}
}
new money = GetEntData(client, gAccount);
do
{
if (bool:i_clients_maxlimit[client] && (i_clients_amount[client] >= i_clients_maxlimit[client]) || (i_buy_limit[client] >= i_clients_maxlimit[client]))
{
PrintHintText(client, "%t", "Can't buy, max amount", i_clients_maxlimit[client]);
return Plugin_Handled;
}
money -= cost;
if (money < 0)
{
PrintHintText(client, "%t", "Can't buy, not enough money", i_clients_amount[client]);
EmitSoundToClient(client, SND_CANTBUY);
return Plugin_Handled;
}
SetEntData(client, gAccount, money);
i_clients_amount[client]++;
i_buy_limit[client]++;
boughtamount++;
} while (--dummy_amount);
if (boughtamount)
{
PrintHintText(client, "%t", "Mines", i_clients_amount[client]);
EmitSoundToClient(client, SND_BUYMINE);
Forward_OnPostBuy(client, boughtamount, boughtamount*cost);
}
return Plugin_Handled;
}
/*
------------------------------------------------
*/
public Action:Command_PlantMine(client, argc)
{
if (!client || !b_enable || !IsClientInGame(client))
{
return Plugin_Continue;
}
if (!i_clients_amount[client])
{
PrintHintText(client, "%t", "Mines", i_clients_amount[client]);
return Plugin_Handled;
}
if (!IsPlayerAlive(client))
{
PrintHintText(client, "%t", "Can't plant, while dead");
return Plugin_Handled;
}
decl color[3];
switch (GetClientTeam(client))
{
case 2 :
{
StringToColor(s_color_t, color, 255);
}
case 3 :
{
StringToColor(s_color_ct, color, 255);
}
default :
{
PrintHintText(client, "%t", "Can't use, while spec");
return Plugin_Handled;
}
}
decl Float:delay_time, dummy_damage, dummy_radius, health, dummy_color[3];
delay_time = f_activate_time;
dummy_damage = i_explode_damage;
dummy_radius = i_explode_radius;
health = i_health;
dummy_color = color;
new Action:result = Forward_OnPlantMine(client, delay_time, dummy_damage, dummy_radius, health, dummy_color);
switch (result)
{
case Plugin_Handled, Plugin_Stop :
{
return result;
}
case Plugin_Continue :
{
delay_time = f_activate_time;
dummy_damage = i_explode_damage;
dummy_radius = i_explode_radius;
health = i_health;
dummy_color = color;
}
}
new mine;
if ((mine = PlantMine(client, delay_time, dummy_damage, dummy_radius, health, dummy_color)) == -1)
return Plugin_Handled;
Forward_OnMinePlanted(client, mine, delay_time, dummy_damage, dummy_radius, health, dummy_color);
switch (i_clients_amount[client])
{
case -1 :
{
PrintHintText(client, "%t", "Infinity mines");
}
default :
{
i_clients_amount[client]--;
PrintHintText(client, "%t", "Mines", i_clients_amount[client]);
}
}
return Plugin_Handled;
}
public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon)
{
static iPrevButtons[MAXPLAYERS+1];
if (!b_allow_pickup || IsFakeClient(client) || !IsPlayerAlive(client))
return Plugin_Continue;
if ((buttons & IN_USE) && !(iPrevButtons[client] & IN_USE))
{
OnButtonPressed(client);
}
iPrevButtons[client] = buttons;
return Plugin_Continue;
}
OnButtonPressed(client)
{
new Handle:trace = TraceRay(client);
new ent = -1;
if (TR_DidHit(trace) && (ent = TR_GetEntityIndex(trace)) > MaxClients)
{
CloseHandle(trace);
new owner = GetClientByLasermine(ent);
if (owner == -1)
{
return;
}
if (owner == client)
{
PickupLasermine(client, ent, owner);
return;
}
if (GetClientTeam(owner) == GetClientTeam(client))
{
if (b_allow_friendly_pickup)
{
PickupLasermine(client, ent, owner);
}
}
else if (b_allow_enemy_pickup)
{
PickupLasermine(client, ent, owner);
}
}
else
CloseHandle(trace);
}
PickupLasermine(client, lasermine, owner)
{
if (i_clients_amount[client] >= 0 && i_clients_amount[client] == AddClientLasermines(client))
{
return;
}
new Action:result = Forward_OnPrePickup(client, lasermine, owner);
switch (result)
{
case Plugin_Handled, Plugin_Stop :
{
return;
}
}
AcceptEntityInput(lasermine, "KillHierarchy");
if (i_clients_amount[client] >= 0)
PrintHintText(client, "%t", "Mines", i_clients_amount[client]);
else
PrintHintText(client, "%t", "Infinity mines");
EmitSoundToClient(client, SND_BUYMINE);
Forward_OnPostPickup(client, lasermine, owner);
}
Handle:TraceRay(client)
{
new Float:startent[3], Float:angle[3], Float:end[3];
GetClientEyePosition(client, startent);
GetClientEyeAngles(client, angle);
GetAngleVectors(angle, end, NULL_VECTOR, NULL_VECTOR);
NormalizeVector(end, end);
startent[0] = startent[0] + end[0] * 10.0;
startent[1] = startent[1] + end[1] * 10.0;
startent[2] = startent[2] + end[2] * 10.0;
end[0] = startent[0] + end[0] * 80.0;
end[1] = startent[1] + end[1] * 80.0;
end[2] = startent[2] + end[2] * 80.0;
return TR_TraceRayFilterEx(startent, end, CONTENTS_SOLID, RayType_EndPoint, FilterPlayers);
}
/*
------------------------------------------------
*/
PlantMine(client, Float:activation_delay = 0.0, explode_damage, explode_radius, const health = 0, const color[3] = {255, 255, 255})
{
if (activation_delay > 10.0)
{
activation_delay = 10.0;
}
else if (activation_delay < 0.0)
{
activation_delay = 0.0;
}
new Handle:trace = TraceRay(client);
decl Float:end[3], Float:normal[3], Float:beamend[3];
if (TR_DidHit(trace) && TR_GetEntityIndex(trace) < 1)
{
TR_GetEndPosition(end, trace);
TR_GetPlaneNormal(trace, normal);
CloseHandle(trace);
GetVectorAngles(normal, normal);
TR_TraceRayFilter(end, normal, CONTENTS_SOLID, RayType_Infinite, FilterAll);
TR_GetEndPosition(beamend, INVALID_HANDLE);
new ent = CreateEntityByName("prop_physics_override");
if (ent == -1 || !IsValidEdict(ent))
{
LogError("Could not create entity \"prop_physics_override\"");
return -1;
}
new beament = CreateEntityByName("env_beam");
if (beament == -1 || !IsValidEdict(beament))
{
LogError("Could not create entity \"env_beam\"");
return -1;
}
decl String:start[30], String:tmp[200];
Format(start, sizeof(start), "Beam%i", beament);
SetEntityModel(ent, MDL_MINE);
decl String:buffer[16];
IntToString(explode_damage, buffer, sizeof(buffer));
DispatchKeyValue(ent, "ExplodeDamage", buffer);
IntToString(explode_radius, buffer, sizeof(buffer));
DispatchKeyValue(ent, "ExplodeRadius", buffer);
DispatchKeyValue(ent, "spawnflags", "3");
DispatchSpawn(ent);
AcceptEntityInput(ent, "DisableMotion");
SetEntityMoveType(ent, MOVETYPE_NONE);
TeleportEntity(ent, end, normal, NULL_VECTOR);
SetEntProp(ent, Prop_Data, "m_nSolidType", 6);
SetEntProp(ent, Prop_Data, "m_CollisionGroup", 11);
if (health)
{
SetEntProp(ent, Prop_Data, "m_takedamage", 2);
SetEntProp(ent, Prop_Data, "m_iHealth", health);
}
Format(tmp, sizeof(tmp), "%s,Kill,,0,-1", start);
DispatchKeyValue(ent, "OnBreak", tmp);
EmitSoundToAll(SND_MINEPUT, ent);
// Set keyvalues on the beam.
DispatchKeyValue(beament, "targetname", start);
DispatchKeyValue(beament, "damage", "0");
DispatchKeyValue(beament, "framestart", "0");
DispatchKeyValue(beament, "BoltWidth", "4.0");
DispatchKeyValue(beament, "renderfx", "0");
DispatchKeyValue(beament, "TouchType", "3"); // 0 = none, 1 = player only, 2 = NPC only, 3 = player or NPC, 4 = player, NPC or physprop
DispatchKeyValue(beament, "framerate", "0");
DispatchKeyValue(beament, "decalname", "Bigshot");
DispatchKeyValue(beament, "TextureScroll", "35");
DispatchKeyValue(beament, "HDRColorScale", "1.0");
DispatchKeyValue(beament, "texture", MDL_LASER);
DispatchKeyValue(beament, "life", "0"); // 0 = infinite, beam life time in seconds
DispatchKeyValue(beament, "StrikeTime", "1"); // If beam life time not infinite, this repeat it back
DispatchKeyValue(beament, "LightningStart", start);
DispatchKeyValue(beament, "spawnflags", "0"); // 0 disable, 1 = start on, etc etc. look from hammer editor
DispatchKeyValue(beament, "NoiseAmplitude", "0"); // straight beam = 0, other make noise beam
DispatchKeyValue(beament, "Radius", "256");
DispatchKeyValue(beament, "renderamt", "100");
DispatchKeyValue(beament, "rendercolor", "0 0 0");
AcceptEntityInput(beament, "TurnOff");
SetEntityModel(beament, MDL_LASER);
TeleportEntity(beament, beamend, NULL_VECTOR, NULL_VECTOR); // Teleport the beam
SetEntPropVector(beament, Prop_Data, "m_vecEndPos", end);
SetEntPropFloat(beament, Prop_Data, "m_fWidth", 3.0);
SetEntPropFloat(beament, Prop_Data, "m_fEndWidth", 3.0);
SetEntPropEnt(beament, Prop_Data, "m_hOwnerEntity", client); // Sets the owner of the beam
SetEntPropEnt(ent, Prop_Data, "m_hMoveChild", beament);
SetEntPropEnt(beament, Prop_Data, "m_hEffectEntity", ent);
new Handle:datapack = CreateDataPack();
WritePackCell(datapack, beament);
WritePackCell(datapack, ent);
WritePackCell(datapack, color[0]);
WritePackCell(datapack, color[1]);
WritePackCell(datapack, color[2]);
WritePackString(datapack, start);
CreateTimer(activation_delay, OnActivateLaser, datapack, TIMER_FLAG_NO_MAPCHANGE|TIMER_HNDL_CLOSE);
SDKHook(ent, SDKHook_OnTakeDamage, OnTakeDamage);
return ent;
}
else
CloseHandle(trace);
return -1;
}
public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype)
{
if (IsEntityLasermine(victim))
{
if (1 <= attacker <= MaxClients)
{
new client = GetClientByLasermine(victim);
if ((client != -1) && (client != attacker) && (GetClientTeam(client) == GetClientTeam(attacker)))
{
return Plugin_Handled;
}
return Plugin_Continue;
}
else if (!IsEntityLasermine(inflictor))
{
return Plugin_Handled;
}
}
return Plugin_Continue;
}
/*
------------------------------------------------
*/
public bool:FilterAll(entity, contentsMask)
{
return false;
}
public bool:FilterPlayers(entity, contentsMask)
{
return !(1 <= entity <= MaxClients);
}
public Action:OnActivateLaser(Handle:timer, any:hDataPack)
{
ResetPack(hDataPack);
decl String:start[30], String:tmp[200], color[3];
new beament = ReadPackCell(hDataPack);
new ent = ReadPackCell(hDataPack);
color[0] = ReadPackCell(hDataPack);
color[1] = ReadPackCell(hDataPack);
color[2] = ReadPackCell(hDataPack);
ReadPackString(hDataPack, start, sizeof(start));
if (!IsValidEdict(beament) || !IsValidEdict(ent))
{
return Plugin_Stop;
}
AcceptEntityInput(beament, "TurnOn");
SetEntityRenderColor(beament, color[0], color[1], color[2]);
Format(tmp, sizeof(tmp), "%s,TurnOff,,0.001,-1", start);
DispatchKeyValue(beament, "OnTouchedByEntity", tmp);
Format(tmp, sizeof(tmp), "%s,TurnOn,,0.002,-1", start);
DispatchKeyValue(beament, "OnTouchedByEntity", tmp);
EmitSoundToAll(SND_MINEACT, ent);
return Plugin_Stop;
}
/*
N A T I V E S
------------------------------------------------
*/
public Native_AddMines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
return 0;
}
else if (!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not in game", client);
return 0;
}
new amount = GetNativeCell(2);
new bool:limit = bool:GetNativeCell(3);
if (amount <= 0)
{
return i_clients_amount[client];
}
if (i_clients_amount[client] < 0)
{
return -1;
}
i_clients_amount[client] += amount;
if (limit)
{
if (i_clients_amount[client] > i_clients_maxlimit[client])
{
i_clients_amount[client] = i_clients_maxlimit[client];
}
}
return i_clients_amount[client];
}
public Native_SetMines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
return false;
}
else if (!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not in game", client);
return false;
}
new amount = GetNativeCell(2);
new bool:limit = bool:GetNativeCell(3);
if (amount < -1)
{
amount = -1;
}
i_clients_amount[client] = amount;
if (limit)
{
if (i_clients_amount[client] > i_clients_maxlimit[client])
{
i_clients_amount[client] = i_clients_maxlimit[client];
}
}
return true;
}
public Native_SubstractMines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
return 0;
}
else if (!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not in game", client);
return 0;
}
new amount = GetNativeCell(2);
if (i_clients_amount[client] == -1)
{
return i_clients_amount[client];
}
if (amount <= 0)
{
return i_clients_amount[client];
}
i_clients_amount[client] -= amount;
if (i_clients_amount[client] < 0)
{
i_clients_amount[client] = 0;
}
return i_clients_amount[client];
}
public Native_GetMines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
return 0;
}
else if (!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not in game", client);
return 0;
}
return i_clients_amount[client];
}
public Native_ClearMapMines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
return;
}
else if (!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not in game", client);
return;
}
OnClientDisconnect(client);
}
public Native_PlantMine(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
return false;
}
else if (!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not in game", client);
return false;
}
new Float:f_delay = GetNativeCell(2);
new i_exp_damage = GetNativeCell(3);
new i_exp_radius = GetNativeCell(4);
new health = GetNativeCell(5);
decl color[3]; GetNativeArray(6, color, sizeof(color));
new mine;
if ((mine = PlantMine(client, f_delay, i_exp_damage, i_exp_radius, health, color)) != -1)
{
Forward_OnMinePlanted(client, mine, f_delay, i_exp_damage, i_exp_radius, health, color);
}
return (mine != -1);
}
public Native_IsLasermine(Handle:plugin, numParams)
{
new entity = GetNativeCell(1);
if (entity <= MaxClients || !IsValidEdict(entity))
{
return false;
}
decl String:g_szModel[PLATFORM_MAX_PATH];
GetEntPropString(entity, Prop_Data, "m_ModelName", g_szModel, sizeof(g_szModel));
return (StrEqual(g_szModel, MDL_MINE, false) && GetEntPropEnt(entity, Prop_Data, "m_hMoveChild") != -1);
}
public Native_GetClientByLasermine(Handle:plugin, numParams)
{
new entity = GetNativeCell(1);
new beam;
if ((beam = GetBeamByLasermine(entity)) == -1)
{
return -1;
}
return GetEntPropEnt(beam, Prop_Data, "m_hOwnerEntity");
}
public Native_SetClientMaxLasermines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
}
else if (!IsClientAuthorized(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not authorized", client);
}
new amount = GetNativeCell(2);
if (amount < -1)
{
amount = -1;
}
i_clients_maxlimit[client] = amount;
i_clients_myamount[client] = amount;
b_used_by_native[client] = true;
}
public Native_ResetClientMaxLasermines(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
}
else if (!IsClientConnected(client))
{
ThrowNativeError(SP_ERROR_NOT_FOUND, "Client %i is not connected", client);
}
OnClientConnected(client);
}
public Native_GetBeamByLasermine(Handle:plugin, numParams)
{
new entity = GetNativeCell(1);
if (IsEntityLasermine(entity))
{
return GetEntPropEnt(entity, Prop_Data, "m_hMoveChild");
}
return -1;
}
public Native_GetLasermineByBeam(Handle:plugin, numParams)
{
new mine = GetEntPropEnt(GetNativeCell(1), Prop_Data, "m_hEffectEntity");
if (mine != -1 && IsEntityLasermine(mine))
{
return mine;
}
return -1;
}
/*
F O R W A R D S
------------------------------------------------
*/
Action:Forward_OnPlantMine(client, &Float:activate_time, &exp_damage, &exp_radius, &health, color[3])
{
decl Action:result;
result = Plugin_Continue;
Call_StartForward(h_fwdOnPlantLasermine);
Call_PushCell(client);
Call_PushFloatRef(activate_time);
Call_PushCellRef(exp_damage);
Call_PushCellRef(exp_radius);
Call_PushCellRef(health);
Call_PushArrayEx(color, sizeof(color), SM_PARAM_COPYBACK);
Call_Finish(result);
return result;
}
Forward_OnMinePlanted(client, mine, Float:activate_time, exp_damage, exp_radius, health, color[3])
{
Call_StartForward(h_fwdOnLaserminePlanted);
Call_PushCell(client);
Call_PushCell(mine);
Call_PushFloat(activate_time);
Call_PushCell(exp_damage);
Call_PushCell(exp_radius);
Call_PushCell(health);
Call_PushArray(color, sizeof(color));
Call_Finish();
}
Action:Forward_OnPreHit(victim, &attacker, &beam, &lasermine, &damage)
{
decl Action:result;
result = Plugin_Continue;
Call_StartForward(h_fwdOnPreHitByLasermine);
Call_PushCell(victim);
Call_PushCellRef(attacker);
Call_PushCellRef(beam);
Call_PushCellRef(lasermine);
Call_PushCellRef(damage);
Call_Finish(result);
return result;
}
Forward_OnPostHit(victim, attacker, beam, lasermine, damage)
{
Call_StartForward(h_fwdOnPostHitByLasermine);
Call_PushCell(victim);
Call_PushCell(attacker);
Call_PushCell(beam);
Call_PushCell(lasermine);
Call_PushCell(damage);
Call_Finish();
}
Action:Forward_OnPreBuy(client, &amount, &price)
{
decl Action:result;
result = Plugin_Continue;
Call_StartForward(h_fwdOnPreBuyLasermine);
Call_PushCell(client);
Call_PushCellRef(amount);
Call_PushCellRef(price);
Call_Finish(result);
return result;
}
Forward_OnPostBuy(client, amount, sum)
{
Call_StartForward(h_fwdOnPostBuyLasermine);
Call_PushCell(client);
Call_PushCell(amount);
Call_PushCell(sum);
Call_Finish();
}
Action:Forward_OnPrePickup(client, lasermine, owner)
{
decl Action:result;
result = Plugin_Continue;
Call_StartForward(h_fwdOnPrePickupLasermine);
Call_PushCell(client);
Call_PushCell(lasermine);
Call_PushCell(owner);
Call_Finish(result);
return result;
}
Forward_OnPostPickup(client, lasermine, owner)
{
Call_StartForward(h_fwdOnPostPickupLasermine);
Call_PushCell(client);
Call_PushCell(lasermine);
Call_PushCell(owner);
Call_Finish();
}
/*
S T O C K S
------------------------------------------------
*/
stock bool:StringToColor(const String:str[], color[3], const defvalue = -1)
{
new bool:result = false;
decl String:Splitter[3][64];
if (ExplodeString(str, " ", Splitter, sizeof(Splitter), sizeof(Splitter[])) == 3 && String_IsNumeric(Splitter[0]) && String_IsNumeric(Splitter[1]) && String_IsNumeric(Splitter[2]))
{
color[0] = StringToInt(Splitter[0]);
color[1] = StringToInt(Splitter[1]);
color[2] = StringToInt(Splitter[2]);
result = true;
}
else
{
color[0] = defvalue;
color[1] = defvalue;
color[2] = defvalue;
}
return result;
}
stock bool:String_IsNumeric(const String:str[])
{
new x=0;
new numbersFound=0;
if (str[x] == '+' || str[x] == '-')
x++;
while (str[x] != '\0')
{
if (IsCharNumeric(str[x]))
numbersFound++;
else
return false;
x++;
}
if (!numbersFound)
return false;
return true;
}
Am I on the correct path here or missing something?
|
|