Raised This Month: $32 Target: $400
 8% 

Tau Cannon Help ( pev_owner )


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Carpex
Junior Member
Join Date: Mar 2018
Old 05-26-2020 , 01:51   Tau Cannon Help ( pev_owner )
Reply With Quote #1

How can I adapt this plugin for fun?
I don't know anything about pev_owner, so the friendly fire kills the plugin owner when it opens.
< Sorry , my english is not good >
Code:
/*
	[ZP] Extra Item: Tau Cannon
	Copyright (C) 2009-2010 by NiHiLaNTh

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
	In addition, as a special exception, the author gives permission to
	link the code of this program with the Half-Life Game Engine ("HL
	Engine") and Modified Game Libraries ("MODs") developed by Valve,
	L.L.C ("Valve"). You must obey the GNU General Public License in all
	respects for all of the code used other than the HL Engine and MODs
	from Valve. If you modify this file, you may extend this exception
	to your version of the file, but you are not obligated to do so. If
	you do not wish to do so, delete this exception statement from your
	version.
	
	--- Introduction ---
	This plugin adds new weapon - Tau Cannon.Basically, this is almost
	the same weapon as in Half-Life.An experimental, highly unstable weapon. 
	One of the most important abilities is that it can shoot through walls, 
	making it so that you can't take cover against it. The gauss's primary 
	fire shoots out tiny spurts that are only effective in close to medium 
	range due to its erratic spread. You can charge up the gauss by holding 
	down alternate fire; the longer you charge it up, the stronger it gets. 
	The longer you charge it up is directly proportional to the thickness 
	of the wall you can shoot through. Lookout campers, retribution has come.
	
	---CVARs---
	zp_tcannon_oneround - Should Tau Cannon be in players inventory only for 1 round?
	zp_tcannon_dmgprim - Primary attack damage
	zp_tcannon_dmgsec - Maximal secondary attack damage
	zp_tcannon_clip - Clip amount
	
	--- Credits ---
	Arkshine, HL SDK, meTaLiCroSS and more...
	
	--- Changelog ---
	1.0 - Initial release.
	1.1 - Added some statics
	1.2 - Fixed ammo buy bug
	    - Fixed possible server crash
*/	
	
#include < amxmodx >
#include < cstrike >
#include < csx >
#include < engine >
#include < fakemeta >
#include < hamsandwich >
#include < fun >
#include < xs >
#include < zombieplague >

// Plugin information
#define Plugin	"[ZP] Extra Item: Tau Cannon"
#define Version	"1.2"
#define Author	"NiHiLaNTh"

// Maxplayers
const MaxPlayers = 32

// Weapon models
new const g_szModelGaussP[ ] = "models/p_gauss.mdl"
new const g_szModelGaussV[ ] = "models/v_alt_gauss.mdl"
new const g_szModelGaussW[ ] = "models/w_gauss.mdl"

// Weapon sounds
new const g_szSoundGaussFire[ ] = "weapons/gauss2.wav"
new const g_szSoundGaussSpin[ ] = "ambience/pulsemachine.wav"
new const g_szSoundElectro1[ ] = "weapons/electro4.wav"
new const g_szSoundElectro2[ ] = "weapons/electro5.wav"
new const g_szSoundElectro3[ ] = "weapons/electro6.wav"

// Some gauss/beam stuff
#define GAUSS_REFIRERATE	0.2 // Primary attack
#define GAUSS_REFIRERATE2	0.1 // Secondary attack(you shouldnt change this!)
#define GAUSS_RECOIL		-2.0 // Only X axis!
#define GAUSS_CHARGETIME	4.0 // From HLSDK
#define GAUSS_RELOADTIME	2.0 // Reload time
#define BEAM_RED		255 // Red amount
#define BEAM_GREEN		128 // Green amount
#define BEAM_BLUE		0 // Blue amount
#define BEAM_ALPHA		255 // Brightness(Alpha)
#define BALL_AMOUNT		8 // How many balls should appear :p

// Ammo given when buy weapons	
new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
1, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }

// Max. bp ammo amount
new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
	5, 120, 200, // This is gauss max bp ammo.Change it if you want!
32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }

// Weapon ammo ID's
new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }

// Player variables
new g_iHasGauss[ MaxPlayers+1 ] // Whether player has gauss
new g_iSoundState[ MaxPlayers+1 ] // Weapon sound state
new g_bInAttack[ MaxPlayers+1 ] // Current gauss attack state
new g_iCurrentWeapon[ MaxPlayers+1 ] // Current weapon player is holding
new Float:g_flLastShotTime[ MaxPlayers+1 ] // Last shot time
new Float:g_fflPlayAfterShock[ MaxPlayers+1 ] // Play aftershock sound
new Float:g_flWeaponIdleTime[ MaxPlayers+1 ] // Weapon idle time
new Float:g_flNextAmmoBurn[ MaxPlayers+1 ] // Next ammo burn time
new Float:g_flStartCharge[ MaxPlayers+1 ] // Weapon start charge
new Float:g_flAmmoStartCharge[ MaxPlayers+1 ] // Ammo start charge
new bool:g_bIsAlive[ MaxPlayers+1 ] // Whether player is alive
new bool:g_bIsConnected[ MaxPlayers+1 ] // Whether player is connected
new bool:g_bPrimaryFire[ MaxPlayers+1 ] // Does this weapon is using primary attack ?
new bool:g_bKilledByLaser[ MaxPlayers+1 ] // Imma firin mah lazor O.o

// CVAR pointers
new cvar_oneround // Whether gun should be only for 1 round
new cvar_dmgprim // Primary attack damage
new cvar_dmgsec // Secondary attack damage
new cvar_clip // Clip amount

// Cached CVAR
new g_pOneRound
new Float:g_pDmgPrim
new Float:g_pDmgSec
new g_pClip

// Global varibles
new g_iMaxPlayers // Maxplayers
new bool:g_bGameRestart // Detect game restart
new g_iBeam // Beam sprite
new g_iBalls // Balls :p
new g_iGaussID // Item ID
new gmsgScreenFade // Screen fade
new gmsgAmmoPickup // Ammo pickup

// CS Offsets
const m_pPlayer = 41
const m_flNextPrimaryAttack = 46
const m_flNextSecondaryAttack = 47
const m_flTimeWeaponIdle = 48
const m_iPrimaryAmmoType = 49
const m_iClip = 51
const m_fInReload = 54
const m_flNextAttack  = 83
const m_rgAmmo_player_Slot0 = 376

// Macro 
#define is_user_valid_connected(%1)		( 1 <= %1 <= g_iMaxPlayers && g_bIsConnected [ %1 ] )
#define is_user_in_water(%1)			( pev ( %1, pev_waterlevel ) == 3 )
#define VectorSubtract(%1,%2,%3)		( %3[ 0 ] = %1[ 0 ] - %2[ 0 ], %3[ 1 ] = %1[ 1 ] - %2[ 1 ], %3[ 2 ] = %1[ 2 ] - %2[ 2 ] )
#define VectorAdd(%1,%2,%3)			( %3[ 0 ] = %1[ 0 ] + %2[ 0 ], %3[ 1 ] = %1[ 1 ] + %2[ 2 ], %3[ 2 ] = %1[ 2 ] + %2[ 2 ] )
#define VectorScale(%1,%2,%3)    		( %3[ 0 ] = %2 * %1[ 0 ], %3[ 1 ] = %2 * %1[ 1 ], %3[ 2 ] = %2 * %1[ 2 ] )
#define VectorLength(%1)         		( floatsqroot ( %1[ 0 ] * %1[ 0 ] + %1[ 1 ] * %1[ 1 ] + %1[ 2 ] * %1[ 2 ] ) )

// Hack!Custom fields
#define pev_weaponkey		pev_impulse
#define pev_bpammo		pev_iuser3

// Misc stuff
#define FCVAR_FLAGS		( FCVAR_SERVER | FCVAR_SPONLY | FCVAR_UNLOGGED )
#define GAUSS_WEAPONKEY	42856
#define NULLENT		-1
#define FFADE_IN		0x0000
#define UNIT_SECOND		(1<<12)

// Entity classnames
new const g_szClassPlayer[ ] = "player"
new const g_szClassM249[ ] = "weapon_m249"

// Primary weapon bitsum
const PRIMARY_WEAPONS_BITSUM = (1<<CSW_SCOUT)|(1<<CSW_XM1014)|(1<<CSW_MAC10)|(1<<CSW_AUG)|(1<<CSW_UMP45)|(1<<CSW_SG550)|(1<<CSW_GALIL)|(1<<CSW_FAMAS)|(1<<CSW_AWP)|(1<<CSW_MP5NAVY)|(1<<CSW_M249)|(1<<CSW_M3)|(1<<CSW_M4A1)|(1<<CSW_TMP)|(1<<CSW_G3SG1)|(1<<CSW_SG552)|(1<<CSW_AK47)|(1<<CSW_P90)

// Animation sequnces
enum
{
	gauss_idle,
	gauss_idle2,
	gauss_fidget,
	gauss_spinup,
	gauss_spin,
	gauss_fire,
	gauss_fire2,
	gauss_holster,
	gauss_draw
}

// Precache
public plugin_precache( )
{
	// Weapon models
	precache_model( g_szModelGaussP )
	precache_model( g_szModelGaussV )
	precache_model( g_szModelGaussW )
	
	// Sounds
	precache_sound( g_szSoundGaussFire )
	precache_sound( g_szSoundGaussSpin )
	precache_sound( g_szSoundElectro1 )
	precache_sound( g_szSoundElectro2 )
	precache_sound( g_szSoundElectro3 )
	precache_sound( "items/9mmclip1.wav" )
	
	// Sprites
	g_iBeam = precache_model( "sprites/smoke.spr" )
	g_iBalls = precache_model( "sprites/hotglow.spr" )
}

// Initialization
public plugin_init( )
{
	// New plugin
	register_plugin( Plugin, Version, Author )
	
	// For Game-Monitor support
	register_cvar( "zp_tcannon_version", Version, FCVAR_FLAGS )
	
	// New extra item
	g_iGaussID = zp_register_extra_item( "Tau Cannon", 30, ZP_TEAM_HUMAN )
	
	// Client commands
	register_clcmd( "buyammo1", "fn_BuyAmmo" )
	register_clcmd( "buyammo2", "fn_BuyAmmo" )
	
	// Events
	register_event( "CurWeapon", "EV_CurWeapon", "be", "1=1" )
	register_event( "DeathMsg", "EV_DeathMsg", "a" )
	register_event( "HLTV", "EV_RoundStart", "a", "1=0", "2=0" )
	register_event( "TextMsg", "EV_GameRestart", "a", "2=#Game_Commencing", "2=#Game_will_restart_in" )
	
	// FakeMeta forwards
	register_forward( FM_SetModel, "fw_SetModel" )
	register_forward( FM_CmdStart, "fw_CmdStart" )
	register_forward( FM_UpdateClientData, "fw_UpdateClientData_Post", 1 )
	register_forward( FM_PlayerPreThink, "fw_PlayerPreThink" )
	
	// HamSandwich forwards
	RegisterHam( Ham_Spawn, g_szClassPlayer, "fw_PlayerSpawn_Post", 1 )
	RegisterHam( Ham_Item_Deploy, g_szClassM249, "fw_TCannonDeploy_Post", 1 )
	RegisterHam( Ham_Item_Holster, g_szClassM249, "fw_TCannonHolster_Post", 1 )
	RegisterHam( Ham_Item_AddToPlayer, g_szClassM249, "fw_TCannonAddToPlayer" )
	RegisterHam( Ham_Item_PostFrame, g_szClassM249, "fw_TCannonPostFrame" )
	RegisterHam( Ham_Weapon_Reload, g_szClassM249, "fw_TCannonReload_Post", 1 )
	
	// CVARs are in Load_Cvars( ) function!
	
	// Messages
	register_message( get_user_msgid( "DeathMsg" ), "fn_DeathMsg" )
	gmsgScreenFade = get_user_msgid( "ScreenFade" )
	gmsgAmmoPickup = get_user_msgid( "AmmoPickup" )
	
	// Store maxplayers in a global variable
	g_iMaxPlayers = get_maxplayers( )
}	

// Configuration
public plugin_cfg( )
{
	// Cache CVARs
	set_task( 1.5, "Load_Cvars" )
}

// ------------------------------- Game Events ----------------------------------------

// Client connected
public client_connect( Player )
{
	// Make a lot of updates
	g_iHasGauss[ Player ] = false
	g_bInAttack[ Player ] = 0
	g_fflPlayAfterShock[ Player ] = 0.0
	g_flWeaponIdleTime[ Player ] = 0.0
	g_bPrimaryFire[ Player ] = false
	g_bIsAlive[ Player ] = false
	g_bIsConnected[ Player ] = true
}

// Client disconnected
public client_disconnect( Player )
{
	// Only few important updates
	g_bIsAlive[ Player ] = false
	g_bIsConnected[ Player ] = false
}

// Someone selected our extra item
public zp_extra_item_selected( Player, Item )
{
	// Tau Cannon
	if ( Item == g_iGaussID )
	{
		// Drop all primary weapons
		UTIL_DropPrimary( Player )
		
		// Update
		g_iHasGauss[ Player ] = true
		
		// Give m249
		give_item( Player, "weapon_m249" )
		
		// Find weapon entity
		new iEnt = find_ent_by_owner( NULLENT, g_szClassM249, Player )
		
		// Apply new clip
		cs_set_weapon_ammo( iEnt, g_pClip )
		
		// Back pack ammo
		cs_set_user_bpammo( Player, CSW_M249, MAXBPAMMO[ 20 ] )
	}
}

// Player is trying to buy something
public fn_BuyAmmo( Player )
{
	// Not alive
	if( !g_bIsAlive[ Player ] )
		return PLUGIN_HANDLED
	
	// Dont have Tau Cannon
	if( !g_iHasGauss[ Player ] )
		return PLUGIN_CONTINUE
	
	// Retrieve ammo pack amount
	static iAmmoPack
	iAmmoPack = zp_get_user_ammo_packs( Player )
	
	// Out of ammo packs
	if( iAmmoPack <= 0 )
		return PLUGIN_HANDLED
	
	// Get players weapons
	static weapons[ 32 ], num, i, currentammo, weaponid, refilled
	num = 0 // reset passed weapons count (bugfix)
	refilled = false
	get_user_weapons( Player, weapons, num )
	
	// Loop through them and give the right ammo type
	for( i = 0; i < num; i++ )
	{
		// Prevents re-indexing the array
		weaponid = weapons[ i ]
		
		// Primary and secondary only
		if( MAXBPAMMO[ weaponid ] > 2 )
		{
			// Get current ammo of the weapon
			currentammo = cs_get_user_bpammo( Player, weaponid)
			
			// Check if we are close to the BP ammo limit
			if (currentammo < MAXBPAMMO[weaponid]-BUYAMMO[weaponid])
			{
				// Flash ammo in hud
				message_begin(MSG_ONE_UNRELIABLE, gmsgAmmoPickup, _, Player )
				write_byte(AMMOID[weaponid]) // ammo id
				write_byte(BUYAMMO[weaponid]) // ammo amount
				message_end()
				
				// Increase BP ammo
				cs_set_user_bpammo ( Player, weaponid, currentammo + BUYAMMO[weaponid])
				
				refilled = true
			}
			else if (currentammo < MAXBPAMMO[weaponid])
			{
				// Flash ammo in hud
				message_begin(MSG_ONE_UNRELIABLE, gmsgAmmoPickup, _, Player )
				write_byte(AMMOID[weaponid]) // ammo id
				write_byte(MAXBPAMMO[weaponid]-currentammo) // ammo amount
				message_end()
				
				// Reached the limit
				cs_set_user_bpammo ( Player, weaponid, MAXBPAMMO[weaponid])
				
				refilled = true
			}
		}
	}
	
	// Weapons already have full ammo
	if (!refilled) return PLUGIN_HANDLED
	
	// Deduce ammo packs, play clip purchase sound, and notify the player
	zp_set_user_ammo_packs( Player, --iAmmoPack )
	engfunc(EngFunc_EmitSound, Player, CHAN_ITEM, "items/9mmclip1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
	client_print( Player, print_chat, "[ZP] You purchased extra ammo for your guns." )
	
	return PLUGIN_HANDLED
}	

// Current weapon player is holding
public EV_CurWeapon( Player )
{
	// Not alive
	if( !g_bIsAlive[ Player ] )
		return PLUGIN_CONTINUE
	
	// Update
	g_iCurrentWeapon[ Player ] = read_data( 2 )
	
	return PLUGIN_CONTINUE
}

// Someone died
public EV_DeathMsg( )
{
	// Get victim
	static iVictim
	iVictim = read_data( 2 )
	
	// Not connected
	if( !is_user_valid_connected( iVictim ) )
		return
	
	// Update
	g_bIsAlive[ iVictim ] = false
	
	// Check if victim has gauss
	if( g_iHasGauss[ iVictim ] && !is_user_bot( iVictim ) )
	{
		// Force to drop
		engclient_cmd( iVictim, "drop weapon_m249" )
	}
}

// Round started
public EV_RoundStart( )
{
	// Restart/One round only
	if( g_bGameRestart || g_pOneRound )
	{
		// Reset array value
		arrayset( g_iHasGauss, false, MaxPlayers+1 )
	}
	
	// Update
	g_bGameRestart = false
}

// Game restart
public EV_GameRestart( )
{
	// Update
	g_bGameRestart = true
}

// Hook death message
public fn_DeathMsg( Player, Dest, iEntity )
{
	// Get victim
	static iVictim, iKiller
	iKiller = get_msg_arg_int( 1 )
	iVictim = get_msg_arg_int( 2 )
	
	// Not connected
	if( !is_user_valid_connected( iVictim ) || iKiller == iVictim )
		return PLUGIN_CONTINUE
	
	// We were killed by laser
	if ( g_bKilledByLaser[ iVictim ] )
	{
		// Replace name in console
		set_msg_arg_string ( 4, "tau cannon" )
	}
	return PLUGIN_CONTINUE
}

// ------------------------------- Forwards ----------------------------------------

// Replace world model
public fw_SetModel ( Entity, const Model [ ] )
{
	// Prevent invalid entity messages
	if( !pev_valid( Entity ) )
		return FMRES_IGNORED
	
	// Not w_awp.mdl
	if( !equal( Model, "models/w_m249.mdl" ) )
		return FMRES_IGNORED
	
	// Get entity classname
	static szClassname[ 32 ]
	pev( Entity, pev_classname, szClassname, charsmax( szClassname ) )
	
	// Not weaponbox
	if( !equal( szClassname, "weaponbox" ) )
		return FMRES_IGNORED
	
	// Get owner
	static iOwner
	iOwner = pev( Entity, pev_owner )
	
	// Get awp ID
	static iWeaponID
	iWeaponID = find_ent_by_owner( NULLENT, g_szClassM249, Entity )
	
	// Make sure that we have gauss
	if( g_iHasGauss [ iOwner ] && is_valid_ent( iWeaponID ) )
	{
		// Hack! Store weaponkey
		set_pev( iWeaponID, pev_weaponkey, GAUSS_WEAPONKEY )
		
		// Hack! Store bp ammo
		set_pev( iWeaponID, pev_bpammo, cs_get_user_bpammo( iOwner, CSW_M249 ) )
		
		// Update
		g_iHasGauss[ iOwner ] = false
		
		// Replace models
		engfunc( EngFunc_SetModel, Entity, g_szModelGaussW )
		return FMRES_SUPERCEDE
	}
	return FMRES_IGNORED
}

// Command start
public fw_CmdStart( Player, UC_Handle, Seed )
{
	// Not alive/dont have gauss/not m249
	if( !g_bIsAlive[ Player ] || !g_iHasGauss[ Player ] || g_iCurrentWeapon[ Player ] != CSW_M249 )
		return FMRES_IGNORED
	
	// Retrieve pressed button bitsum
	static iButtons
	iButtons = get_uc( UC_Handle, UC_Buttons )
	
	// Retrieve game time
	static Float:flGameTime
	flGameTime = get_gametime( )
	
	// Retrieve weapon entity
	static iEnt
	iEnt = find_ent_by_owner( NULLENT, g_szClassM249, Player )
	
	// Retrieve clip amount
	static iClip
	iClip = cs_get_weapon_ammo( iEnt )
	
	// Primary attack
	if( iButtons & IN_ATTACK )
	{
		// Remove attack buttons from their button mask
		iButtons &= ~IN_ATTACK
		set_uc( UC_Handle, UC_Buttons, iButtons )
		
		// Prevent too fast shooting
		if( flGameTime - g_flLastShotTime[ Player ] < GAUSS_REFIRERATE )
			return FMRES_IGNORED
		
		// Dont fire while reloading
		if( get_pdata_int( iEnt, m_fInReload, 4 ) )
			return FMRES_IGNORED
		
		// Not enough clip/under water
		if( iClip < 2 || is_user_in_water( Player ) )
		{
			// Emit empty sound
			ExecuteHamB( Ham_Weapon_PlayEmptySound, iEnt )
			return FMRES_IGNORED
		}
		
		// Update
		g_bPrimaryFire[ Player ] = true
		
		// Start to fire
		StartFire( Player )
		
		// Decrease clip
		cs_set_weapon_ammo( iEnt, iClip-2 )
		
		// Reset weapon attack status
		g_bInAttack[ Player ] = 0
		
		// Set time when idle animation should be played
		g_flWeaponIdleTime[ Player ] = flGameTime + 1.0
		
		// Remember last shot time
		g_flLastShotTime[ Player ] = flGameTime
	}
	// Secondary attack
	else if( iButtons & IN_ATTACK2 )
	{
		// Prevent too fast shooting
		if( flGameTime - g_flLastShotTime[ Player ] < GAUSS_REFIRERATE2 )
			return FMRES_IGNORED
		
		// Dont fire while reloading
		if( get_pdata_int( iEnt, m_fInReload, 4 ) )
			return FMRES_IGNORED
		
		// Are we swimming ?
		if( is_user_in_water( Player ) )
		{
			// We are in a middle of attack
			if( g_bInAttack[ Player ] != 0 )
			{
				// Stop attack
				emit_sound( Player, CHAN_WEAPON, g_szSoundElectro1, VOL_NORM, ATTN_NORM, 0, 80 + random_num( 0, 0x3f ) )
				
				// Gun idle
				UTIL_PlayWeaponAnimation( Player, gauss_idle )
				return FMRES_IGNORED
			}
			else
			{
				// Empty sound
				ExecuteHamB( Ham_Weapon_PlayEmptySound, iEnt )
				return FMRES_IGNORED
			}
		}
		
		// Get player oldbuttons
		static iOldButtons
		iOldButtons = pev( Player, pev_oldbuttons )
		
		// Make sure that we are holding secondary attack button
		if( iOldButtons & IN_ATTACK2 )
		{
			// Which attack state do we have
			switch ( g_bInAttack[ Player ] )
			{
				case 0: // Attack start
				{
					// Out of ammo
					if ( iClip <= 0 )
					{
						ExecuteHamB( Ham_Weapon_PlayEmptySound, iEnt )
						return FMRES_IGNORED
					}
					
					// We aren't using primary attack anymore
					g_bPrimaryFire[ Player ] = false
					
					// Decrease clip
					cs_set_weapon_ammo( iEnt, --iClip )
					
					// Update
					g_flNextAmmoBurn[ Player ] = flGameTime
					
					// Send spinup animation
					UTIL_PlayWeaponAnimation( Player, gauss_spinup )
					
					// Update attack state
					g_bInAttack[ Player ] = 1
					
					// Next idle time
					g_flWeaponIdleTime[ Player ] = flGameTime + 0.5
					
					// Update
					g_flStartCharge[ Player ] = flGameTime
					g_flAmmoStartCharge[ Player ] = flGameTime + GAUSS_CHARGETIME
					
					// Update sound state
					g_iSoundState[ Player ] = 0
					
					// Spin sound
					emit_sound( Player, CHAN_WEAPON, g_szSoundGaussSpin, VOL_NORM, ATTN_NORM, g_iSoundState[Player ], 110 )
					
					// Change sound state
					g_iSoundState[ Player ] = SND_CHANGE_PITCH
				}
				case 1: // In a middle of attack
				{
					if( g_flWeaponIdleTime[ Player ] < flGameTime )
					{
						// Spin anim
						UTIL_PlayWeaponAnimation( Player, gauss_spin )
						
						// Update state
						g_bInAttack[ Player ] = 2
					}
				}
				default: // End of attack
				{
					// During the charging process, eat one bit of ammo every once in a while
					if( flGameTime >= g_flNextAmmoBurn[ Player ] && g_flNextAmmoBurn[ Player ] != 1000 )
					{
						// Decrease clip
						cs_set_weapon_ammo( iEnt, --iClip )
						
						// Next time when ammo should be decreased
						g_flNextAmmoBurn[ Player ] = flGameTime + 0.1
					}
					
					// Shit!We run out of ammo
					if( iClip <= 0 )
					{
						// Force gun to fire
						StartFire( Player )
						
						// Reset weapon state
						g_bInAttack[ Player ] = 0
						
						// Set next idle time
						g_flWeaponIdleTime[ Player ] = flGameTime + 1.0
					}
					
					// Gun is fully charged up
					if( flGameTime >= g_flAmmoStartCharge[ Player ] )
					{
						// Dont eat any more ammo!
						g_flNextAmmoBurn[ Player ] = 1000.0
					}
					
					// Calculate pitch
					static Float:flPitch
					flPitch = ( flGameTime - g_flStartCharge[ Player ] ) * ( 150 / GAUSS_CHARGETIME ) + 100
					
					// Pitch shouldnt be THAT big
					if ( flPitch > 250 )
					{
						flPitch = 250.0
					}
					
					// Spin sound
					emit_sound( Player, CHAN_WEAPON, g_szSoundGaussSpin, VOL_NORM, ATTN_NORM, ( g_iSoundState[ Player ] == SND_CHANGE_PITCH ) ? 1 : 0, floatround( flPitch ) )
					
					// Hack for going through level transitions
					g_iSoundState[ Player ] = SND_CHANGE_PITCH
					
					// We are charing way too long!
					if( g_flStartCharge[ Player ] < flGameTime - 10 )
					{
						// ZAP!
						emit_sound( Player, CHAN_WEAPON, g_szSoundElectro1, VOL_NORM, ATTN_NORM, 0, 80 + random_num( 0, 0x3f ) )
						emit_sound( Player, CHAN_VOICE, g_szSoundElectro3, VOL_NORM, ATTN_NORM, 0, 80 + random_num( 0, 0x3f ) )
						
						// Reset fire state
						g_bInAttack[ Player ] = 0
						
						// Next idle time
						g_flWeaponIdleTime[ Player ] = flGameTime + 1.0
						
						// Damage player
						ExecuteHamB( Ham_TakeDamage, Player, 0, Player, 50.0, DMG_SHOCK )
						
						// Make screen fade
						UTIL_ScreenFade( Player, UNIT_SECOND*2, UNIT_SECOND/2, FFADE_IN, 255, 128, 0, 128 )
						
						// Idle animation
						UTIL_PlayWeaponAnimation( Player, gauss_idle )
					}
				}
			}
			
			// Update
			g_flLastShotTime[ Player ] = flGameTime
		}
	}
	
	return FMRES_HANDLED
}

// Update client data post
public fw_UpdateClientData_Post ( Player, SendWeapons, CD_Handle )
{
	// Not alive / dont have gauss/ not m249
	if ( !g_bIsAlive [ Player ] || !g_iHasGauss [ Player ] || g_iCurrentWeapon [ Player ] != CSW_M249 )
		return FMRES_IGNORED
	
	// Block default sounds/animations
	set_cd ( CD_Handle, CD_flNextAttack, halflife_time ( ) + 0.001 )
	return FMRES_HANDLED
}

// Player pre think
public fw_PlayerPreThink( Player )
{
	// Not alive / dont have gauss/ not m249
	if ( !g_bIsAlive [ Player ] || !g_iHasGauss [ Player ] || g_iCurrentWeapon [ Player ] != CSW_M249 )
		return
	
	// Play aftershock discharge
	if( g_fflPlayAfterShock[ Player ] && g_fflPlayAfterShock[ Player ] < get_gametime( ) )
	{
		// Randomly play sound
		switch( random_num(0, 3 ) )
		{
			case 0: emit_sound( Player, CHAN_WEAPON, g_szSoundElectro1,random_float( 0.7, 0.8 ), ATTN_NORM, 0, PITCH_NORM )
				case 1: emit_sound( Player, CHAN_WEAPON, g_szSoundElectro2,random_float( 0.7, 0.8 ), ATTN_NORM, 0, PITCH_NORM )
				case 2: emit_sound( Player, CHAN_WEAPON, g_szSoundElectro3,random_float( 0.7, 0.8 ), ATTN_NORM, 0, PITCH_NORM )
				case 3: return // No sound
			}
		
		// Reset discharge
		g_fflPlayAfterShock[ Player ] = 0.0
	}
	
	// Check if we are in a middle of attack
	if( g_bInAttack[ Player ] != 0 )
	{
		// Check if have released attack2 button
		if( get_gametime( ) - g_flLastShotTime[ Player ] > 0.2 )
		{
			// Start to fire
			StartFire( Player )
			
			// Reset attack state
			g_bInAttack[ Player ] = 0
			
			// Next idle time
			g_flWeaponIdleTime[ Player ] = get_gametime( ) + 2.0 
		}
	}
	else
	{
		// Force to idle
		WeaponIdle( Player )
	}
}

// Player respawned
public fw_PlayerSpawn_Post( Player )
{
	// Not alive
	if( !is_user_alive( Player ) )
		return
	
	// Update
	g_bIsAlive[ Player ] = true
}

// Guass deploy
public fw_TCannonDeploy_Post( iEnt )
{
	// Get owner
	static Player
	Player = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss?
	if ( g_iHasGauss[ Player ] )
	{
		// Replace models
		set_pev( Player, pev_viewmodel2, g_szModelGaussV )
		set_pev( Player, pev_weaponmodel2, g_szModelGaussP )
		
		// Deploy animation
		UTIL_PlayWeaponAnimation( Player, gauss_draw )
		
		// Reset aftershock
		g_fflPlayAfterShock[ Player ] = 0.0
	}
}

// Gauss holster
public fw_TCannonHolster_Post( iEnt )
{
	// Get owner
	static Player
	Player = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss?
	if ( g_iHasGauss[ Player ] )
	{
		// Check if player is still attacking
		if( g_bInAttack[ Player ] )
		{
			// Bug!Bug!Stop spin sound
			emit_sound( Player, CHAN_WEAPON, g_szSoundGaussSpin, 0.0, 0.0, SND_STOP, 0 )
			
			// Attack
			StartFire( Player )
		}
		
		// Holster animation
		UTIL_PlayWeaponAnimation( Player, gauss_holster )
		
		// Reset attack status
		g_bInAttack[ Player ] = 0
	}
}

// Add Gauss to players inventory
public fw_TCannonAddToPlayer( iEnt, Player )
{
	// Prevent run-time errors
	if( is_valid_ent( iEnt ) && is_user_valid_connected( Player ) )
	{
		// Seems that player has picked up a gauss
		if( pev( iEnt, pev_weaponkey ) == GAUSS_WEAPONKEY )
		{
			// Update variable
			g_iHasGauss[ Player ] = true
			
			// Update bp ammo
			cs_set_user_bpammo( Player, CSW_M249, pev( iEnt, pev_bpammo ) )
			
			// Reset weapon options
			set_pev( iEnt, pev_weaponkey, 0 )
			set_pev( iEnt, pev_bpammo, 0 )
			
			return HAM_HANDLED
		}
	}
	return HAM_IGNORED
}

// Gauss post frame
public fw_TCannonPostFrame( iEnt )
{
	// Get owner
	static iOwner
	iOwner = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss?
	if ( g_iHasGauss[ iOwner ] )
	{
		// Reload offset
		static fInReload 
		fInReload = get_pdata_int ( iEnt, m_fInReload,4 )
		
		// Next attack time
		static Float:flNextAttack 
		flNextAttack = get_pdata_float (iOwner, m_flNextAttack, 5 )
		
		// Clip
		static iClip
		iClip = get_pdata_int ( iEnt, m_iClip, 4 )
		
		// Ammo type
		static iAmmoType 
		iAmmoType = m_rgAmmo_player_Slot0 + get_pdata_int ( iEnt, m_iPrimaryAmmoType, 4 )
		
		// BP ammo
		static iBpAmmo
		iBpAmmo = get_pdata_int ( iOwner, iAmmoType, 5 )	
		
		// Reloading
		if ( fInReload && flNextAttack <= 0.0 )
		{
			// Calculate the difference
			static j 
			j = min ( g_pClip - iClip, iBpAmmo )
			
			// Set new clip
			set_pdata_int ( iEnt, m_iClip, iClip + j, 4 )
			
			// Decrease 'x' bullets from backpack(depending on new clip)
			set_pdata_int( iOwner, iAmmoType, iBpAmmo-j, 5 )
			
			// Not reloding anymore
			set_pdata_int ( iEnt, m_fInReload, 0, 4 )
			fInReload = 0
		}
		
		// Get buttons
		static iButton ; iButton = pev ( iOwner, pev_button)
		
		// Attack/Attack2 buttons and next prim/sec attack time hasnt' come yet
		if( ( iButton & IN_ATTACK2 && get_pdata_float ( iEnt, m_flNextSecondaryAttack, 4 ) <= 0.0)
		|| ( iButton & IN_ATTACK && get_pdata_float ( iEnt, m_flNextPrimaryAttack, 4 ) <= 0.0) )
		{
			return
		}
	
		// Reload button / not reloading
		if( iButton & IN_RELOAD && !fInReload )
		{
			// Old clip is more/equal than/to new
			if( iClip >= g_pClip )
			{
				// Remove reload button
				set_pev ( iOwner, pev_button, iButton & ~IN_RELOAD )
				
				// Idle animation
				UTIL_PlayWeaponAnimation ( iOwner, gauss_idle )
				
				// Idle time
				g_flWeaponIdleTime[ iOwner ] = get_gametime( ) + 0.5
			}
			else
			{
				// Out of ammo
				if ( !iBpAmmo )
					return
					
				// Reload weapon
				UTIL_WeaponReload ( iOwner, iEnt )
			}
		}
	}
}

// Gauss reload post
public fw_TCannonReload_Post( iEnt )
{
	// Get owner
	static Player
	Player = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss and is he in a middle of reloading ?
	if ( g_iHasGauss[ Player ] && get_pdata_int( iEnt, m_fInReload, 4 ) )
	{
		// Reload
		UTIL_WeaponReload( Player, iEnt )
	}
}

// ------------------------------- Internal Functions ----------------------------------------

// Gauss start fire
public StartFire( Player )
{
	// This var holds damage
	static Float:flDamage
	
	// Make vectors
	UTIL_MakeVectors( Player )
	
	// Get gametime
	static Float:flGameTime
	flGameTime = get_gametime( )
	
	// This is maximal possible damage from secondary attack!
	if( flGameTime - g_flStartCharge[ Player ] > GAUSS_CHARGETIME )
	{
		flDamage = g_pDmgSec
	}
	else
	{
		// The longer you hold attack button - the bigger is damage
		flDamage = g_pDmgSec * ( ( flGameTime - g_flStartCharge[ Player ] ) / GAUSS_CHARGETIME )
	}
	
	// Primary attack do less damage
	if( g_bPrimaryFire[ Player ] )
	{
		flDamage = g_pDmgPrim
	}
	
	// Make sure that we are not ending attack
	if( g_bInAttack[ Player ] != 3 )
	{
		// Secondary attack can pop you up in the air.Not primary attack!
		if( !g_bPrimaryFire[ Player ] )
		{
			// Current players velocity
			static Float:flVel[ 3 ], Float:v_forward[ 3 ]
			pev( Player, pev_velocity, flVel )
			global_get( glb_v_forward, v_forward )
			
			// Try to affect only vertical velocity
			VectorMS( flVel, flDamage * 5.0, v_forward, flVel )
			
			// Jump!
			set_pev( Player, pev_velocity, flVel )
		}
	}
	
	// Recoil
	static Float:flRecoil[ 3 ]
	flRecoil[ 0 ] = GAUSS_RECOIL
	set_pev( Player, pev_punchangle, flRecoil )
	
	// Fire animation
	UTIL_PlayWeaponAnimation( Player, gauss_fire2 )
	
	// Fire sound
	static Float:flResult
	flResult = 0.5 + flDamage * ( 1.0 / 400.0 )
	
	if( flResult > 1.0 )
	{
		flResult = 1.0
	}
	
	emit_sound( Player, CHAN_WEAPON, g_szSoundGaussFire, flResult, ATTN_NORM, 0, 85 + random_num( 0, 0x1f ) )
	
	// Get players aimpoint position
	static Float:vecDest[ 3 ]
	global_get( glb_v_forward, vecDest )
	
	// Calculate start position
	static Float:vecSrc[ 3 ]
	UTIL_GetGunPosition( Player, vecSrc )
	
	// Time until aftershock 'static discharge' sound
	g_fflPlayAfterShock[ Player ] = flGameTime + random_float( 0.3, 0.8 )
	
	// Fire!
	Fire( Player, vecSrc, vecDest, flDamage )
}

// Fire!
Fire( Player, Float:vecOrigSrc[ ], Float:vecDir[ ], Float:flDamage )
{
	// Start position
	static Float:vecSrc[ 3 ]
	xs_vec_copy( vecOrigSrc, vecSrc )
	
	// Calculate end position
	static Float:vecDest[ 3 ]
	VectorMA( vecSrc, 8192.0, vecDir, vecDest )
	
	// Few trace handles
	static tr, beam_tr
	
	// Max fraction
	static Float:flMaxFrac
	flMaxFrac = 1.0
	
	// Total
	static nTotal
	nTotal = 0
	
	// Does this beam punched the wall ?
	static bool:fHasPunched
	fHasPunched = false
	
	// Does this is first beam
	static bool:fFirstBeam
	fFirstBeam = true
	
	// Max hits
	static nMaxHits
	nMaxHits = 10
	
	// Entity whoch should be ignored
	static pEntToIgnore
	
	// Make sure that beam will'be able to cause damage
	while( flDamage > 10 && nMaxHits > 0 )
	{
		// Decrease hit count
		nMaxHits--
		
		// Draw a trace line
		engfunc( EngFunc_TraceLine, vecSrc, vecDest, DONT_IGNORE_MONSTERS, pEntToIgnore, tr )
		
		// We'll never get outside!
		if( get_tr2( tr, TR_AllSolid ) )
			break
		
		// Get entity which was hit
		static pEntity
		pEntity = Instance( get_tr2( tr, TR_pHit ) )	
		
		// Get vector end position
		static Float:vecEnd[ 3 ]
		get_tr2( tr, TR_vecEndPos, vecEnd )
		
		// Its first beam	
		if( fFirstBeam )
		{
			// Add muzzleflash
			set_pev( Player, pev_effects, pev(Player, pev_effects) | EF_MUZZLEFLASH )
			
			// Its not first anymore
			fFirstBeam = false
			
			// Add
			nTotal += 26
			
			// Draw beam
			engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecSrc, 0 )
			//message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
			write_byte( TE_BEAMENTPOINT ) // Temp. entity ID
			write_short( Player | 0x1000 ) // Start entity
			engfunc( EngFunc_WriteCoord, vecEnd[ 0 ] ) // End position X
			engfunc( EngFunc_WriteCoord, vecEnd[ 1 ] ) // End position Y
			engfunc( EngFunc_WriteCoord, vecEnd[ 2 ] ) // End position Z
			write_short( g_iBeam ) // Sprite index
			write_byte( 0 ) // Start frame
			write_byte( 1 ) // Frame rate
			write_byte( 1 ) // Life
			write_byte( g_bPrimaryFire[ Player ] ? 16 : 25 ) // Line width
			write_byte( 0 ) // Noise amplitude
			write_byte( 255 )
			write_byte( 128 )
			write_byte( 0 )
			write_byte( 255 ) // Alpha
			write_byte( 0 ) // Scroll speed
			message_end( )
		}
		else
		{
			// Draw beam
			engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecSrc, 0 )
			write_byte( TE_BEAMPOINTS ) // Temp. entity ID
			engfunc( EngFunc_WriteCoord, vecSrc[ 0 ] ) // Start position X
			engfunc( EngFunc_WriteCoord, vecSrc[ 1 ] ) // Start position Y
			engfunc( EngFunc_WriteCoord, vecSrc[ 2 ] ) // Start position Z
			engfunc( EngFunc_WriteCoord, vecEnd[ 0 ] ) // End position X
			engfunc( EngFunc_WriteCoord, vecEnd[ 1 ] ) // End position Y
			engfunc( EngFunc_WriteCoord, vecEnd[ 2 ] ) // End position Z
			write_short( g_iBeam ) // Sprite index
			write_byte( 0 ) // Start frame
			write_byte( 1 ) // Frame rate
			write_byte( 1 ) // Life
			write_byte( g_bPrimaryFire[ Player ] ? 15 : 25 ) // Line width
			write_byte( 0 ) // Noise amplitude
			write_byte( 255 )
			write_byte( 128 )
			write_byte( 0 )
			write_byte( 255 )
			write_byte( 0 ) // Scroll speed
			message_end( )
		}
		
		// Check if this entity should take any damage
		if( pev( pEntity, pev_takedamage ) != DAMAGE_NO )
		{
			// Check if this is player and zombie
			if( is_user_valid_connected( pEntity ) && zp_get_user_zombie( pEntity ) )
			{
				// Retrieve health
				static iHealth
				iHealth = get_user_health( pEntity )
			
				// We should be alive
				if( iHealth - flDamage >= 1 )
				{
					// Cause some damage
					ExecuteHamB( Ham_TakeDamage, pEntity, 0, Player, flDamage, DMG_BULLET | DMG_ALWAYSGIB )
				}
				else
				{
					// Die
					g_bKilledByLaser[ pEntity ] = true
					ExecuteHamB( Ham_Killed, pEntity, Player, 2 )
					g_bKilledByLaser[ pEntity ] = false
				}
			}
		}
		
		// Check if this entity should reflect our beam
		if( ReflectGauss( pEntity ) )
		{
			static Float:n
			
			// Return normal vector in a spot we hit
			static Float:vecPlaneNormal[ 3 ]
			get_tr2( tr, TR_vecPlaneNormal, vecPlaneNormal )
			
			// Calculate dot product
			n = - xs_vec_dot( vecPlaneNormal, vecDir )
			
			// 60 degrees
			if ( 0 < n < 0.5 )
			{
				static Float:r[ 3 ]
				VectorMA( vecDir, 2.0 * n, vecPlaneNormal, r )
				
				// Get vector end position
				get_tr2( tr, TR_vecEndPos, vecEnd )
				
				// Get trace fraction
				static Float:trflFraction
				get_tr2( tr, TR_flFraction, trflFraction )
				
				// Calculate fraction
				flMaxFrac = flMaxFrac - trflFraction
				
				// Copy vectors
				xs_vec_copy( r, vecDir )
				
				// Make more vector calculations
				VectorMA( vecEnd, 8.0, vecDir, vecSrc )
				VectorMA( vecSrc, 8192.0, vecDir, vecDest )
			
				// Undone!Do radius damage
				
				// Increase
				nTotal += 34
				
				if( n == 0 )
				{
					// Lose energy
					n = 0.1
				}
				
				// Calculate new damage
				flDamage = flDamage * ( 1 - n )
			}
			else
			{
				// Add gun shot decal on the world
				FX_GunShotDecal( vecEnd, pEntity )
				
				// Add glowing sprite on the world
				FX_TempSprite( vecEnd, 6, floatround( flDamage / 255.0 ) )
				
				// Increase
				nTotal += 13
				
				// Limit it to one hole punch
				if( fHasPunched )
					break
				
				// Update	
				fHasPunched = true	
				
				// Try punching through wall if secondary attack (primary is incapable of 
				// breaking through)
				if( !g_bPrimaryFire[ Player ] )
				{
					// Retrieve vector end position
					get_tr2( tr, TR_vecEndPos, vecEnd )
					
					// Modify start origin
					static Float:vecStart[ 3 ]
					VectorMA( vecEnd, 8.0, vecDir, vecStart )
					
					// Draw another trace line
					engfunc( EngFunc_TraceLine, vecSrc, vecDest, DONT_IGNORE_MONSTERS, pEntToIgnore, beam_tr )
					
					// We'll never get outside
					if( !get_tr2( beam_tr, TR_AllSolid ) )
					{
						// Get end position
						static Float:vecBeamEndPos[ 3 ]
						get_tr2( beam_tr, TR_vecEndPos, vecBeamEndPos )
						
						// Trace backwards to find exit point
						engfunc( EngFunc_TraceLine, vecBeamEndPos, vecEnd, DONT_IGNORE_MONSTERS, pEntToIgnore, beam_tr )
						
						// Again get end position
						get_tr2( beam_tr, TR_vecEndPos, vecBeamEndPos )
						
						static Float:ns, Float:vecSub[ 3 ]
						
						// Subtract vectors
						xs_vec_sub( vecBeamEndPos, vecEnd, vecSub )
						
						// Get vector length
						ns = xs_vec_len( vecSub )
						
						if( ns < flDamage )
						{
							// Lose enery
							if( ns == 0 )
							{
								ns = 1.0
							}
							
							// Decrease damage
							flDamage -= ns
							
							// Subtract
							static Float:vecCalc[ 3 ]
							VectorSubtract( vecEnd, vecDir, vecCalc )
							
							// Absorbtion balls
							FX_SpriteTrail( vecEnd, vecCalc, BALL_AMOUNT, 15, 3, 25, 25 )
							
							// Add gun shot decal on the world
							FX_GunShotDecal( vecBeamEndPos, pEntity )
							
							// And glowing sprite
							FX_TempSprite( vecBeamEndPos, 6, floatround( flDamage / 255.0 ) )
							
							// Subtract
							VectorSubtract( vecBeamEndPos, vecDir, vecCalc )
							
							// Absorbtion balls
							FX_SpriteTrail( vecEnd, vecCalc, BALL_AMOUNT, 15, 3, 25, 25 )
							
							// Increase shit
							nTotal += 21
							
							/*
							// Calculate radius damage
							static Float:flRadDmg
							flRadDmg = flDamage * 1.75
							
							// Undone.Do radius damage here!
							floatradius( flDamage, flRadDmg, vecBeamEndPos )
							*/
							
							// Increase
							nTotal += 53
							
							VectorMA( vecBeamEndPos, 8.0, vecDir, vecSub )
							
							// Add up vector
							xs_vec_add( vecBeamEndPos, vecDir, vecSrc )
						}
					}
					else
					{
						flDamage = 0.0
					}
				}
				else
				{
					// Primary attack
					if( g_bPrimaryFire [ Player ] )
					{
						// Slug doesn't punch through ever with primary 
						// fire, so leave a little glowy bit and make some balls
						FX_TempSprite( vecEnd, 6, floatround( flDamage / 255.0 ) )
						FX_SpriteTrail( vecEnd, vecDir, BALL_AMOUNT, 15, 3, 25, 25 )
					}
					
					flDamage = 0.0
				}
			}
		}
		else
		{
			// Add up vector
			xs_vec_add( vecEnd, vecDir, vecSrc )
			pEntToIgnore = pEntity
		}
	}
}				

// Register and cache CVARs
public Load_Cvars( )
{
	cvar_oneround = register_cvar( "zp_tcannon_oneround", "0" )
	cvar_dmgprim = register_cvar( "zp_tcannon_dmgprim", "200" )
	cvar_dmgsec = register_cvar( "zp_tcannon_dmgsec", "500" )
	cvar_clip = register_cvar( "zp_tcannon_clip", "100" )
	
	g_pOneRound = get_pcvar_num( cvar_oneround )
	g_pDmgPrim = get_pcvar_float( cvar_dmgprim )
	g_pDmgSec = get_pcvar_float( cvar_dmgsec )
	g_pClip = get_pcvar_num( cvar_clip )
}

// Gauss weapon idle
WeaponIdle( Player )
{
	// Get gametime
	static Float:flGameTime
	flGameTime = get_gametime( )
	
	if( g_flWeaponIdleTime[ Player ] > flGameTime )
		return
	
	// Animation sequence variable
	static iAnim
	
	// Animation randomizer
	static Float:flRand
	flRand = random_float( 0.1, 1.0 )
	
	if( flRand <= 0.5 )
	{
		iAnim = gauss_idle
		g_flWeaponIdleTime[ Player ] = flGameTime + random_float( 10.0, 15.0 )
	}
	else if( flRand <= 0.75 )
	{
		iAnim = gauss_idle2
		g_flWeaponIdleTime[ Player ] = flGameTime + random_float( 10.0, 15.0 )
	}
	else
	{
		iAnim = gauss_fidget
		g_flWeaponIdleTime[ Player ] = flGameTime + 3
	}
	
	// Idle
	UTIL_PlayWeaponAnimation( Player, iAnim )
}	

// Play weapon animation
UTIL_PlayWeaponAnimation( const Player, const Sequence )
{
	set_pev( Player, pev_weaponanim, Sequence )
	
	message_begin( MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = Player )
	write_byte( Sequence )
	write_byte( pev( Player, pev_body ) )
	message_end( )
}				

// Make ScreenFade
UTIL_ScreenFade( Player, Duration, HoldTime, Flags, iRed, iGreen, iBlue, iAlpha )
{
	message_begin( MSG_ONE, gmsgScreenFade, _, Player )
	write_short( Duration )
	write_short( HoldTime )
	write_short( Flags )
	write_byte( iRed )
	write_byte( iGreen )
	write_byte( iBlue )
	write_byte( iAlpha )
	message_end( )
}

// Reload gauss
UTIL_WeaponReload( Player, iEnt )
{
	// Modify time until next attack
	set_pdata_float( Player, m_flNextAttack, GAUSS_RELOADTIME+0.5, 5 )
	
	// Reload animation
	UTIL_PlayWeaponAnimation( Player, gauss_spin )
	
	// Enable reload offset
	set_pdata_int( iEnt, m_fInReload, 1, 4 )
	
	// Modify next idle time
	g_flWeaponIdleTime[ Player ] = get_gametime( ) + GAUSS_RELOADTIME + 1.0 
}

// Drop all primary weapons
UTIL_DropPrimary( Player )
{
	// Get user weapons
	static weapons[ 32 ], num, i, weaponid
	num = 0 // reset passed weapons count (bugfix)
	get_user_weapons( Player, weapons, num )
	
	// Loop through them and drop primaries
	for( i = 0; i < num; i++ )
	{
		// Prevent re-indexing the array
		weaponid = weapons[ i ]
		
		// We definetely are holding primary gun
		if(( (1<<weaponid) & PRIMARY_WEAPONS_BITSUM ) )		
		{
			// Get weapon entity
			static wname[32]
			get_weaponname(weaponid, wname, charsmax(wname))
			
			// Player drops the weapon and looses his bpammo
			engclient_cmd( Player, "drop", wname)
		}
	}
}

// Get gun position
UTIL_GetGunPosition( Player, Float:flOrigin[ ] )
{
	static Float:vf_Origin[ 3 ], Float:vf_ViewOfs[ 3 ]
	
	pev( Player, pev_origin, vf_Origin )
	pev( Player, pev_view_ofs, vf_ViewOfs )
	
	xs_vec_add( vf_Origin, vf_ViewOfs, flOrigin )
}

// Make vectors
UTIL_MakeVectors ( Player )
{
	static Float:flAngle[ 3 ], Float:flPunchAngle[ 3 ]

	pev( Player, pev_v_angle, flAngle )
	pev( Player, pev_punchangle, flPunchAngle )

	xs_vec_add( flAngle, flPunchAngle, flAngle )
	engfunc( EngFunc_MakeVectors, flAngle )
}

// From HL SDK.
VectorMA( Float:a[ ], Float:flScale, Float:b[ ], Float:c[ ] )
{
	c[ 0 ] = a[ 0 ] + flScale * b[ 0 ]
	c[ 1 ] = a[ 1 ] + flScale * b[ 1 ]
	c[ 2 ] = a[ 2 ] + flScale * b[ 2 ]
}

VectorMS( const Float:flSource[ ], const Float:flScale, const Float:flMult[ ], Float:flOutput[ ] )
{
        flOutput[ 0 ] = flSource[ 0 ] - flMult[ 0 ] * flScale
        flOutput[ 1 ] = flSource[ 1 ] - flMult[ 1 ] * flScale
        flOutput[ 2 ] = flSource[ 2 ] - flMult[ 2 ] * flScale
}

// Another stuff from HLSDK
Instance( iEnt )
{
	return iEnt == -1 ? 0 : iEnt
}

// Does this entity should refect gauss?
ReflectGauss( iEnt )
{
		return IsBSPModel( iEnt ) && pev( iEnt, pev_takedamage ) == DAMAGE_NO 
}

// Does this entity is BSP model?
IsBSPModel( iEnt )
{
	return pev( iEnt, pev_solid ) == SOLID_BSP || pev( iEnt, pev_movetype ) == MOVETYPE_PUSHSTEP 
}

// Add gun shot decal on world!
FX_GunShotDecal( Float:flPos[ ], pEntity )
{
	// Draw gunshot
	engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flPos, 0 )
	write_byte( TE_GUNSHOTDECAL ) // Temp.entity ID
	engfunc( EngFunc_WriteCoord, flPos[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, flPos[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, flPos[ 2 ] ) // Position Z
	write_short( pEntity ) // Which entity to mark?
	write_byte( 43 ) // Decal number
	message_end( )
}

// Add glow sprite on world
FX_TempSprite( Float:flPos[ ], iScale, iSize )
{
	engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flPos, 0 )
	write_byte( TE_GLOWSPRITE ) // Temp.entity ID
	engfunc( EngFunc_WriteCoord, flPos[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, flPos[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, flPos[ 2 ] ) // Position Z
	write_short( g_iBalls ) // Sprite index
	write_byte( iScale ) // Scale
	write_byte( iSize ) // Size
	write_byte( 255 ) // Brightness
	message_end( )
}

// Add sprite trail
FX_SpriteTrail( Float:vecStart[ ], Float:vecDest[ ], iCount, iLife, iScale, iVel, iRnd )
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_SPRITETRAIL ) // Sprite trail
	engfunc( EngFunc_WriteCoord, vecStart[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, vecStart[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, vecStart[ 2 ] ) // Position Z
	engfunc( EngFunc_WriteCoord, vecDest[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, vecDest[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, vecDest[ 2 ] ) // Position Z
	write_short( g_iBalls ) // SPrite index
	write_byte( iCount ) // Amount
	write_byte( iLife ) // Life
	write_byte( iScale ) // Scale
	write_byte( iVel ) // Velocity along vector
	write_byte( iRnd ) // Randomness of velocity
	message_end( )
}
Carpex is offline
OciXCrom
Veteran Member
Join Date: Oct 2013
Location: Macedonia
Old 05-26-2020 , 08:11   Re: Tau Cannon Help ( pev_owner )
Reply With Quote #2

What do you mean? I don't understand. How is "fun" related to "pev_owner"?
__________________
OciXCrom is offline
Send a message via Skype™ to OciXCrom
Carpex
Junior Member
Join Date: Mar 2018
Old 05-26-2020 , 09:29   Re: Tau Cannon Help ( pev_owner )
Reply With Quote #3

When I try to shoot the players in the same team, the gun kills the owner.
Code:
/*
	[ZP] Extra Item: Tau Cannon
	Copyright (C) 2009-2010 by NiHiLaNTh

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
	In addition, as a special exception, the author gives permission to
	link the code of this program with the Half-Life Game Engine ("HL
	Engine") and Modified Game Libraries ("MODs") developed by Valve,
	L.L.C ("Valve"). You must obey the GNU General Public License in all
	respects for all of the code used other than the HL Engine and MODs
	from Valve. If you modify this file, you may extend this exception
	to your version of the file, but you are not obligated to do so. If
	you do not wish to do so, delete this exception statement from your
	version.
	
	--- Introduction ---
	This plugin adds new weapon - Tau Cannon.Basically, this is almost
	the same weapon as in Half-Life.An experimental, highly unstable weapon. 
	One of the most important abilities is that it can shoot through walls, 
	making it so that you can't take cover against it. The gauss's primary 
	fire shoots out tiny spurts that are only effective in close to medium 
	range due to its erratic spread. You can charge up the gauss by holding 
	down alternate fire; the longer you charge it up, the stronger it gets. 
	The longer you charge it up is directly proportional to the thickness 
	of the wall you can shoot through. Lookout campers, retribution has come.
	
	---CVARs---
	zp_tcannon_oneround - Should Tau Cannon be in players inventory only for 1 round?
	zp_tcannon_dmgprim - Primary attack damage
	zp_tcannon_dmgsec - Maximal secondary attack damage
	zp_tcannon_clip - Clip amount
	
	--- Credits ---
	Arkshine, HL SDK, meTaLiCroSS and more...
	
	--- Changelog ---
	1.0 - Initial release.
	1.1 - Added some statics
	1.2 - Fixed ammo buy bug
	    - Fixed possible server crash
*/	
	
#include < amxmodx >
#include < cstrike >
#include < csx >
#include < engine >
#include < fakemeta >
#include < hamsandwich >
#include < fun >
#include < xs >

// Plugin information
#define Plugin	"[ZP] Extra Item: Tau Cannon"
#define Version	"1.2"
#define Author	"NiHiLaNTh"

// Maxplayers
const MaxPlayers = 32

// Weapon models
new const g_szModelGaussP[ ] = "models/p_gauss.mdl"
new const g_szModelGaussV[ ] = "models/v_alt_gauss.mdl"
new const g_szModelGaussW[ ] = "models/w_gauss.mdl"

// Weapon sounds
new const g_szSoundGaussFire[ ] = "weapons/gauss2.wav"
new const g_szSoundGaussSpin[ ] = "ambience/pulsemachine.wav"
new const g_szSoundElectro1[ ] = "weapons/electro4.wav"
new const g_szSoundElectro2[ ] = "weapons/electro5.wav"
new const g_szSoundElectro3[ ] = "weapons/electro6.wav"

// Some gauss/beam stuff
#define GAUSS_REFIRERATE	0.2 // Primary attack
#define GAUSS_REFIRERATE2	0.1 // Secondary attack(you shouldnt change this!)
#define GAUSS_RECOIL		-2.0 // Only X axis!
#define GAUSS_CHARGETIME	4.0 // From HLSDK
#define GAUSS_RELOADTIME	2.0 // Reload time
#define BEAM_RED		255 // Red amount
#define BEAM_GREEN		128 // Green amount
#define BEAM_BLUE		0 // Blue amount
#define BEAM_ALPHA		255 // Brightness(Alpha)
#define BALL_AMOUNT		8 // How many balls should appear :p

// Ammo given when buy weapons	
new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
1, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }

// Max. bp ammo amount
new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
	5, 120, 200, // This is gauss max bp ammo.Change it if you want!
32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }

// Weapon ammo ID's
new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }

// Player variables
new g_iHasGauss[ MaxPlayers+1 ] // Whether player has gauss
new g_iSoundState[ MaxPlayers+1 ] // Weapon sound state
new g_bInAttack[ MaxPlayers+1 ] // Current gauss attack state
new g_iCurrentWeapon[ MaxPlayers+1 ] // Current weapon player is holding
new Float:g_flLastShotTime[ MaxPlayers+1 ] // Last shot time
new Float:g_fflPlayAfterShock[ MaxPlayers+1 ] // Play aftershock sound
new Float:g_flWeaponIdleTime[ MaxPlayers+1 ] // Weapon idle time
new Float:g_flNextAmmoBurn[ MaxPlayers+1 ] // Next ammo burn time
new Float:g_flStartCharge[ MaxPlayers+1 ] // Weapon start charge
new Float:g_flAmmoStartCharge[ MaxPlayers+1 ] // Ammo start charge
new bool:g_bIsAlive[ MaxPlayers+1 ] // Whether player is alive
new bool:g_bIsConnected[ MaxPlayers+1 ] // Whether player is connected
new bool:g_bPrimaryFire[ MaxPlayers+1 ] // Does this weapon is using primary attack ?
new bool:g_bKilledByLaser[ MaxPlayers+1 ] // Imma firin mah lazor O.o

// CVAR pointers
new cvar_oneround // Whether gun should be only for 1 round
new cvar_dmgprim // Primary attack damage
new cvar_dmgsec // Secondary attack damage
new cvar_clip // Clip amount

// Cached CVAR
new g_pOneRound
new Float:g_pDmgPrim
new Float:g_pDmgSec
new g_pClip

// Global varibles
new g_iMaxPlayers // Maxplayers
new bool:g_bGameRestart // Detect game restart
new g_iBeam // Beam sprite
new g_iBalls // Balls :p
new g_iGaussID // Item ID
new gmsgScreenFade // Screen fade
new gmsgAmmoPickup // Ammo pickup

// CS Offsets
const m_pPlayer = 41
const m_flNextPrimaryAttack = 46
const m_flNextSecondaryAttack = 47
const m_flTimeWeaponIdle = 48
const m_iPrimaryAmmoType = 49
const m_iClip = 51
const m_fInReload = 54
const m_flNextAttack  = 83
const m_rgAmmo_player_Slot0 = 376

// Macro 
#define is_user_valid_connected(%1)		( 1 <= %1 <= g_iMaxPlayers && g_bIsConnected [ %1 ] )
#define is_user_in_water(%1)			( pev ( %1, pev_waterlevel ) == 3 )
#define VectorSubtract(%1,%2,%3)		( %3[ 0 ] = %1[ 0 ] - %2[ 0 ], %3[ 1 ] = %1[ 1 ] - %2[ 1 ], %3[ 2 ] = %1[ 2 ] - %2[ 2 ] )
#define VectorAdd(%1,%2,%3)			( %3[ 0 ] = %1[ 0 ] + %2[ 0 ], %3[ 1 ] = %1[ 1 ] + %2[ 2 ], %3[ 2 ] = %1[ 2 ] + %2[ 2 ] )
#define VectorScale(%1,%2,%3)    		( %3[ 0 ] = %2 * %1[ 0 ], %3[ 1 ] = %2 * %1[ 1 ], %3[ 2 ] = %2 * %1[ 2 ] )
#define VectorLength(%1)         		( floatsqroot ( %1[ 0 ] * %1[ 0 ] + %1[ 1 ] * %1[ 1 ] + %1[ 2 ] * %1[ 2 ] ) )

// Hack!Custom fields
#define pev_weaponkey		pev_impulse
#define pev_bpammo		pev_iuser3

// Misc stuff
#define FCVAR_FLAGS		( FCVAR_SERVER | FCVAR_SPONLY | FCVAR_UNLOGGED )
#define GAUSS_WEAPONKEY	42856
#define NULLENT		-1
#define FFADE_IN		0x0000
#define UNIT_SECOND		(1<<12)

// Entity classnames
new const g_szClassPlayer[ ] = "player"
new const g_szClassM249[ ] = "weapon_m249"

// Primary weapon bitsum
const PRIMARY_WEAPONS_BITSUM = (1<<CSW_SCOUT)|(1<<CSW_XM1014)|(1<<CSW_MAC10)|(1<<CSW_AUG)|(1<<CSW_UMP45)|(1<<CSW_SG550)|(1<<CSW_GALIL)|(1<<CSW_FAMAS)|(1<<CSW_AWP)|(1<<CSW_MP5NAVY)|(1<<CSW_M249)|(1<<CSW_M3)|(1<<CSW_M4A1)|(1<<CSW_TMP)|(1<<CSW_G3SG1)|(1<<CSW_SG552)|(1<<CSW_AK47)|(1<<CSW_P90)

// Animation sequnces
enum
{
	gauss_idle,
	gauss_idle2,
	gauss_fidget,
	gauss_spinup,
	gauss_spin,
	gauss_fire,
	gauss_fire2,
	gauss_holster,
	gauss_draw
}

// Precache
public plugin_precache( )
{
	// Weapon models
	precache_model( g_szModelGaussP )
	precache_model( g_szModelGaussV )
	precache_model( g_szModelGaussW )
	
	// Sounds
	precache_sound( g_szSoundGaussFire )
	precache_sound( g_szSoundGaussSpin )
	precache_sound( g_szSoundElectro1 )
	precache_sound( g_szSoundElectro2 )
	precache_sound( g_szSoundElectro3 )
	precache_sound( "items/9mmclip1.wav" )
	
	// Sprites
	g_iBeam = precache_model( "sprites/smoke.spr" )
	g_iBalls = precache_model( "sprites/hotglow.spr" )
}

// Initialization
public plugin_init( )
{
	// New plugin
	register_plugin( Plugin, Version, Author )
	
	// For Game-Monitor support
	register_cvar( "zp_tcannon_version", Version, FCVAR_FLAGS )
	
	// New extra item
	register_clcmd("say /tau","zp_extra_item_selected")
	//g_iGaussID = zp_register_extra_item( "Tau Cannon", 30, ZP_TEAM_HUMAN )
	
	// Client commands
	register_clcmd( "buyammo1", "fn_BuyAmmo" )
	register_clcmd( "buyammo2", "fn_BuyAmmo" )
	
	// Events
	register_event( "CurWeapon", "EV_CurWeapon", "be", "1=1" )
	register_event( "DeathMsg", "EV_DeathMsg", "a" )
	register_event( "HLTV", "EV_RoundStart", "a", "1=0", "2=0" )
	register_event( "TextMsg", "EV_GameRestart", "a", "2=#Game_Commencing", "2=#Game_will_restart_in" )
	
	// FakeMeta forwards
	register_forward( FM_SetModel, "fw_SetModel" )
	register_forward( FM_CmdStart, "fw_CmdStart" )
	register_forward( FM_UpdateClientData, "fw_UpdateClientData_Post", 1 )
	register_forward( FM_PlayerPreThink, "fw_PlayerPreThink" )
	
	// HamSandwich forwards
	RegisterHam( Ham_Spawn, g_szClassPlayer, "fw_PlayerSpawn_Post", 1 )
	RegisterHam( Ham_Item_Deploy, g_szClassM249, "fw_TCannonDeploy_Post", 1 )
	RegisterHam( Ham_Item_Holster, g_szClassM249, "fw_TCannonHolster_Post", 1 )
	RegisterHam( Ham_Item_AddToPlayer, g_szClassM249, "fw_TCannonAddToPlayer" )
	RegisterHam( Ham_Item_PostFrame, g_szClassM249, "fw_TCannonPostFrame" )
	RegisterHam( Ham_Weapon_Reload, g_szClassM249, "fw_TCannonReload_Post", 1 )
	
	// CVARs are in Load_Cvars( ) function!
	
	// Messages
	register_message( get_user_msgid( "DeathMsg" ), "fn_DeathMsg" )
	gmsgScreenFade = get_user_msgid( "ScreenFade" )
	gmsgAmmoPickup = get_user_msgid( "AmmoPickup" )
	
	// Store maxplayers in a global variable
	g_iMaxPlayers = get_maxplayers( )
}	

// Configuration
public plugin_cfg( )
{
	// Cache CVARs
	set_task( 1.5, "Load_Cvars" )
}

// ------------------------------- Game Events ----------------------------------------

// Client connected
public client_connect( Player )
{
	// Make a lot of updates
	g_iHasGauss[ Player ] = false
	g_bInAttack[ Player ] = 0
	g_fflPlayAfterShock[ Player ] = 0.0
	g_flWeaponIdleTime[ Player ] = 0.0
	g_bPrimaryFire[ Player ] = false
	g_bIsAlive[ Player ] = false
	g_bIsConnected[ Player ] = true
}

// Client disconnected
public client_disconnected( Player )
{
	// Only few important updates
	g_bIsAlive[ Player ] = false
	g_bIsConnected[ Player ] = false
}

// Someone selected our extra item
public zp_extra_item_selected( Player, Item )
{
	// Tau Cannon
	if ( Item == g_iGaussID )
	{
		// Drop all primary weapons
		UTIL_DropPrimary( Player )
		
		// Update
		g_iHasGauss[ Player ] = true
		
		// Give m249
		give_item( Player, "weapon_m249" )
		
		// Find weapon entity
		new iEnt = find_ent_by_owner( NULLENT, g_szClassM249, Player )
		
		// Apply new clip
		cs_set_weapon_ammo( iEnt, g_pClip )
		
		// Back pack ammo
		cs_set_user_bpammo( Player, CSW_M249, MAXBPAMMO[ 20 ] )
	}
}

// Player is trying to buy something
public fn_BuyAmmo( Player )
{
	// Not alive
	if( !g_bIsAlive[ Player ] )
		return PLUGIN_HANDLED
	
	// Dont have Tau Cannon
	if( !g_iHasGauss[ Player ] )
		return PLUGIN_CONTINUE
	
	// Retrieve ammo pack amount
	static iAmmoPack
	iAmmoPack = cs_get_user_money( Player )
	
	// Out of ammo packs
	if( iAmmoPack <= 0 )
		return PLUGIN_HANDLED
	
	// Get players weapons
	static weapons[ 32 ], num, i, currentammo, weaponid, refilled
	num = 0 // reset passed weapons count (bugfix)
	refilled = false
	get_user_weapons( Player, weapons, num )
	
	// Loop through them and give the right ammo type
	for( i = 0; i < num; i++ )
	{
		// Prevents re-indexing the array
		weaponid = weapons[ i ]
		
		// Primary and secondary only
		if( MAXBPAMMO[ weaponid ] > 2 )
		{
			// Get current ammo of the weapon
			currentammo = cs_get_user_bpammo( Player, weaponid)
			
			// Check if we are close to the BP ammo limit
			if (currentammo < MAXBPAMMO[weaponid]-BUYAMMO[weaponid])
			{
				// Flash ammo in hud
				message_begin(MSG_ONE_UNRELIABLE, gmsgAmmoPickup, _, Player )
				write_byte(AMMOID[weaponid]) // ammo id
				write_byte(BUYAMMO[weaponid]) // ammo amount
				message_end()
				
				// Increase BP ammo
				cs_set_user_bpammo ( Player, weaponid, currentammo + BUYAMMO[weaponid])
				
				refilled = true
			}
			else if (currentammo < MAXBPAMMO[weaponid])
			{
				// Flash ammo in hud
				message_begin(MSG_ONE_UNRELIABLE, gmsgAmmoPickup, _, Player )
				write_byte(AMMOID[weaponid]) // ammo id
				write_byte(MAXBPAMMO[weaponid]-currentammo) // ammo amount
				message_end()
				
				// Reached the limit
				cs_set_user_bpammo ( Player, weaponid, MAXBPAMMO[weaponid])
				
				refilled = true
			}
		}
	}
	
	// Weapons already have full ammo
	if (!refilled) return PLUGIN_HANDLED
	
	// Deduce ammo packs, play clip purchase sound, and notify the player
	cs_set_user_money( Player, --iAmmoPack )
	engfunc(EngFunc_EmitSound, Player, CHAN_ITEM, "items/9mmclip1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
	client_print( Player, print_chat, "[ZP] You purchased extra ammo for your guns." )
	
	return PLUGIN_HANDLED
}	

// Current weapon player is holding
public EV_CurWeapon( Player )
{
	// Not alive
	if( !g_bIsAlive[ Player ] )
		return PLUGIN_CONTINUE
	
	// Update
	g_iCurrentWeapon[ Player ] = read_data( 2 )
	
	return PLUGIN_CONTINUE
}

// Someone died
public EV_DeathMsg( )
{
	// Get victim
	static iVictim
	iVictim = read_data( 2 )
	
	// Not connected
	if( !is_user_valid_connected( iVictim ) )
		return
	
	// Update
	g_bIsAlive[ iVictim ] = false
	
	// Check if victim has gauss
	if( g_iHasGauss[ iVictim ] && !is_user_bot( iVictim ) )
	{
		// Force to drop
		engclient_cmd( iVictim, "drop weapon_m249" )
	}
}

// Round started
public EV_RoundStart( )
{
	// Restart/One round only
	if( g_bGameRestart || g_pOneRound )
	{
		// Reset array value
		arrayset( g_iHasGauss, false, MaxPlayers+1 )
	}
	
	// Update
	g_bGameRestart = false
}

// Game restart
public EV_GameRestart( )
{
	// Update
	g_bGameRestart = true
}

// Hook death message
public fn_DeathMsg( Player, Dest, iEntity )
{
	// Get victim
	static iVictim, iKiller
	iKiller = get_msg_arg_int( 1 )
	iVictim = get_msg_arg_int( 2 )
	
	// Not connected
	if( !is_user_valid_connected( iVictim ) || iKiller == iVictim )
		return PLUGIN_CONTINUE
	
	// We were killed by laser
	if ( g_bKilledByLaser[ iVictim ] )
	{
		// Replace name in console
		set_msg_arg_string ( 4, "tau cannon" )
	}
	return PLUGIN_CONTINUE
}

// ------------------------------- Forwards ----------------------------------------

// Replace world model
public fw_SetModel ( Entity, const Model [ ] )
{
	// Prevent invalid entity messages
	if( !pev_valid( Entity ) )
		return FMRES_IGNORED
	
	// Not w_awp.mdl
	if( !equal( Model, "models/w_m249.mdl" ) )
		return FMRES_IGNORED
	
	// Get entity classname
	static szClassname[ 32 ]
	pev( Entity, pev_classname, szClassname, charsmax( szClassname ) )
	
	// Not weaponbox
	if( !equal( szClassname, "weaponbox" ) )
		return FMRES_IGNORED
	
	// Get owner
	static iOwner
	iOwner = pev( Entity, pev_owner )
	
	// Get awp ID
	static iWeaponID
	iWeaponID = find_ent_by_owner( NULLENT, g_szClassM249, Entity )
	
	// Make sure that we have gauss
	if( g_iHasGauss [ iOwner ] && is_valid_ent( iWeaponID ) )
	{
		// Hack! Store weaponkey
		set_pev( iWeaponID, pev_weaponkey, GAUSS_WEAPONKEY )
		
		// Hack! Store bp ammo
		set_pev( iWeaponID, pev_bpammo, cs_get_user_bpammo( iOwner, CSW_M249 ) )
		
		// Update
		g_iHasGauss[ iOwner ] = false
		
		// Replace models
		engfunc( EngFunc_SetModel, Entity, g_szModelGaussW )
		return FMRES_SUPERCEDE
	}
	return FMRES_IGNORED
}

// Command start
public fw_CmdStart( Player, UC_Handle, Seed )
{
	// Not alive/dont have gauss/not m249
	if( !g_bIsAlive[ Player ] || !g_iHasGauss[ Player ] || g_iCurrentWeapon[ Player ] != CSW_M249 )
		return FMRES_IGNORED
	
	// Retrieve pressed button bitsum
	static iButtons
	iButtons = get_uc( UC_Handle, UC_Buttons )
	
	// Retrieve game time
	static Float:flGameTime
	flGameTime = get_gametime( )
	
	// Retrieve weapon entity
	static iEnt
	iEnt = find_ent_by_owner( NULLENT, g_szClassM249, Player )
	
	// Retrieve clip amount
	static iClip
	iClip = cs_get_weapon_ammo( iEnt )
	
	// Primary attack
	if( iButtons & IN_ATTACK )
	{
		// Remove attack buttons from their button mask
		iButtons &= ~IN_ATTACK
		set_uc( UC_Handle, UC_Buttons, iButtons )
		
		// Prevent too fast shooting
		if( flGameTime - g_flLastShotTime[ Player ] < GAUSS_REFIRERATE )
			return FMRES_IGNORED
		
		// Dont fire while reloading
		if( get_pdata_int( iEnt, m_fInReload, 4 ) )
			return FMRES_IGNORED
		
		// Not enough clip/under water
		if( iClip < 2 || is_user_in_water( Player ) )
		{
			// Emit empty sound
			ExecuteHamB( Ham_Weapon_PlayEmptySound, iEnt )
			return FMRES_IGNORED
		}
		
		// Update
		g_bPrimaryFire[ Player ] = true
		
		// Start to fire
		StartFire( Player )
		
		// Decrease clip
		cs_set_weapon_ammo( iEnt, iClip-2 )
		
		// Reset weapon attack status
		g_bInAttack[ Player ] = 0
		
		// Set time when idle animation should be played
		g_flWeaponIdleTime[ Player ] = flGameTime + 1.0
		
		// Remember last shot time
		g_flLastShotTime[ Player ] = flGameTime
	}
	// Secondary attack
	else if( iButtons & IN_ATTACK2 )
	{
		// Prevent too fast shooting
		if( flGameTime - g_flLastShotTime[ Player ] < GAUSS_REFIRERATE2 )
			return FMRES_IGNORED
		
		// Dont fire while reloading
		if( get_pdata_int( iEnt, m_fInReload, 4 ) )
			return FMRES_IGNORED
		
		// Are we swimming ?
		if( is_user_in_water( Player ) )
		{
			// We are in a middle of attack
			if( g_bInAttack[ Player ] != 0 )
			{
				// Stop attack
				emit_sound( Player, CHAN_WEAPON, g_szSoundElectro1, VOL_NORM, ATTN_NORM, 0, 80 + random_num( 0, 0x3f ) )
				
				// Gun idle
				UTIL_PlayWeaponAnimation( Player, gauss_idle )
				return FMRES_IGNORED
			}
			else
			{
				// Empty sound
				ExecuteHamB( Ham_Weapon_PlayEmptySound, iEnt )
				return FMRES_IGNORED
			}
		}
		
		// Get player oldbuttons
		static iOldButtons
		iOldButtons = pev( Player, pev_oldbuttons )
		
		// Make sure that we are holding secondary attack button
		if( iOldButtons & IN_ATTACK2 )
		{
			// Which attack state do we have
			switch ( g_bInAttack[ Player ] )
			{
				case 0: // Attack start
				{
					// Out of ammo
					if ( iClip <= 0 )
					{
						ExecuteHamB( Ham_Weapon_PlayEmptySound, iEnt )
						return FMRES_IGNORED
					}
					
					// We aren't using primary attack anymore
					g_bPrimaryFire[ Player ] = false
					
					// Decrease clip
					cs_set_weapon_ammo( iEnt, --iClip )
					
					// Update
					g_flNextAmmoBurn[ Player ] = flGameTime
					
					// Send spinup animation
					UTIL_PlayWeaponAnimation( Player, gauss_spinup )
					
					// Update attack state
					g_bInAttack[ Player ] = 1
					
					// Next idle time
					g_flWeaponIdleTime[ Player ] = flGameTime + 0.5
					
					// Update
					g_flStartCharge[ Player ] = flGameTime
					g_flAmmoStartCharge[ Player ] = flGameTime + GAUSS_CHARGETIME
					
					// Update sound state
					g_iSoundState[ Player ] = 0
					
					// Spin sound
					emit_sound( Player, CHAN_WEAPON, g_szSoundGaussSpin, VOL_NORM, ATTN_NORM, g_iSoundState[Player ], 110 )
					
					// Change sound state
					g_iSoundState[ Player ] = SND_CHANGE_PITCH
				}
				case 1: // In a middle of attack
				{
					if( g_flWeaponIdleTime[ Player ] < flGameTime )
					{
						// Spin anim
						UTIL_PlayWeaponAnimation( Player, gauss_spin )
						
						// Update state
						g_bInAttack[ Player ] = 2
					}
				}
				default: // End of attack
				{
					// During the charging process, eat one bit of ammo every once in a while
					if( flGameTime >= g_flNextAmmoBurn[ Player ] && g_flNextAmmoBurn[ Player ] != 1000 )
					{
						// Decrease clip
						cs_set_weapon_ammo( iEnt, --iClip )
						
						// Next time when ammo should be decreased
						g_flNextAmmoBurn[ Player ] = flGameTime + 0.1
					}
					
					// Shit!We run out of ammo
					if( iClip <= 0 )
					{
						// Force gun to fire
						StartFire( Player )
						
						// Reset weapon state
						g_bInAttack[ Player ] = 0
						
						// Set next idle time
						g_flWeaponIdleTime[ Player ] = flGameTime + 1.0
					}
					
					// Gun is fully charged up
					if( flGameTime >= g_flAmmoStartCharge[ Player ] )
					{
						// Dont eat any more ammo!
						g_flNextAmmoBurn[ Player ] = 1000.0
					}
					
					// Calculate pitch
					static Float:flPitch
					flPitch = ( flGameTime - g_flStartCharge[ Player ] ) * ( 150 / GAUSS_CHARGETIME ) + 100
					
					// Pitch shouldnt be THAT big
					if ( flPitch > 250 )
					{
						flPitch = 250.0
					}
					
					// Spin sound
					emit_sound( Player, CHAN_WEAPON, g_szSoundGaussSpin, VOL_NORM, ATTN_NORM, ( g_iSoundState[ Player ] == SND_CHANGE_PITCH ) ? 1 : 0, floatround( flPitch ) )
					
					// Hack for going through level transitions
					g_iSoundState[ Player ] = SND_CHANGE_PITCH
					
					// We are charing way too long!
					if( g_flStartCharge[ Player ] < flGameTime - 10 )
					{
						// ZAP!
						emit_sound( Player, CHAN_WEAPON, g_szSoundElectro1, VOL_NORM, ATTN_NORM, 0, 80 + random_num( 0, 0x3f ) )
						emit_sound( Player, CHAN_VOICE, g_szSoundElectro3, VOL_NORM, ATTN_NORM, 0, 80 + random_num( 0, 0x3f ) )
						
						// Reset fire state
						g_bInAttack[ Player ] = 0
						
						// Next idle time
						g_flWeaponIdleTime[ Player ] = flGameTime + 1.0
						
						// Damage player
						ExecuteHamB( Ham_TakeDamage, Player, 0, Player, 50.0, DMG_SHOCK )
						
						// Make screen fade
						UTIL_ScreenFade( Player, UNIT_SECOND*2, UNIT_SECOND/2, FFADE_IN, 255, 128, 0, 128 )
						
						// Idle animation
						UTIL_PlayWeaponAnimation( Player, gauss_idle )
					}
				}
			}
			
			// Update
			g_flLastShotTime[ Player ] = flGameTime
		}
	}
	
	return FMRES_HANDLED
}

// Update client data post
public fw_UpdateClientData_Post ( Player, SendWeapons, CD_Handle )
{
	// Not alive / dont have gauss/ not m249
	if ( !g_bIsAlive [ Player ] || !g_iHasGauss [ Player ] || g_iCurrentWeapon [ Player ] != CSW_M249 )
		return FMRES_IGNORED
	
	// Block default sounds/animations
	set_cd ( CD_Handle, CD_flNextAttack, halflife_time ( ) + 0.001 )
	return FMRES_HANDLED
}

// Player pre think
public fw_PlayerPreThink( Player )
{
	// Not alive / dont have gauss/ not m249
	if ( !g_bIsAlive [ Player ] || !g_iHasGauss [ Player ] || g_iCurrentWeapon [ Player ] != CSW_M249 )
		return
	
	// Play aftershock discharge
	if( g_fflPlayAfterShock[ Player ] && g_fflPlayAfterShock[ Player ] < get_gametime( ) )
	{
		// Randomly play sound
		switch( random_num(0, 3 ) )
		{
			case 0: emit_sound( Player, CHAN_WEAPON, g_szSoundElectro1,random_float( 0.7, 0.8 ), ATTN_NORM, 0, PITCH_NORM )
				case 1: emit_sound( Player, CHAN_WEAPON, g_szSoundElectro2,random_float( 0.7, 0.8 ), ATTN_NORM, 0, PITCH_NORM )
				case 2: emit_sound( Player, CHAN_WEAPON, g_szSoundElectro3,random_float( 0.7, 0.8 ), ATTN_NORM, 0, PITCH_NORM )
				case 3: return // No sound
			}
		
		// Reset discharge
		g_fflPlayAfterShock[ Player ] = 0.0
	}
	
	// Check if we are in a middle of attack
	if( g_bInAttack[ Player ] != 0 )
	{
		// Check if have released attack2 button
		if( get_gametime( ) - g_flLastShotTime[ Player ] > 0.2 )
		{
			// Start to fire
			StartFire( Player )
			
			// Reset attack state
			g_bInAttack[ Player ] = 0
			
			// Next idle time
			g_flWeaponIdleTime[ Player ] = get_gametime( ) + 2.0 
		}
	}
	else
	{
		// Force to idle
		WeaponIdle( Player )
	}
}

// Player respawned
public fw_PlayerSpawn_Post( Player )
{
	// Not alive
	if( !is_user_alive( Player ) )
		return
	
	// Update
	g_bIsAlive[ Player ] = true
}

// Guass deploy
public fw_TCannonDeploy_Post( iEnt )
{
	// Get owner
	static Player
	Player = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss?
	if ( g_iHasGauss[ Player ] )
	{
		// Replace models
		set_pev( Player, pev_viewmodel2, g_szModelGaussV )
		set_pev( Player, pev_weaponmodel2, g_szModelGaussP )
		
		// Deploy animation
		UTIL_PlayWeaponAnimation( Player, gauss_draw )
		
		// Reset aftershock
		g_fflPlayAfterShock[ Player ] = 0.0
	}
}

// Gauss holster
public fw_TCannonHolster_Post( iEnt )
{
	// Get owner
	static Player
	Player = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss?
	if ( g_iHasGauss[ Player ] )
	{
		// Check if player is still attacking
		if( g_bInAttack[ Player ] )
		{
			// Bug!Bug!Stop spin sound
			emit_sound( Player, CHAN_WEAPON, g_szSoundGaussSpin, 0.0, 0.0, SND_STOP, 0 )
			
			// Attack
			StartFire( Player )
		}
		
		// Holster animation
		UTIL_PlayWeaponAnimation( Player, gauss_holster )
		
		// Reset attack status
		g_bInAttack[ Player ] = 0
	}
}

// Add Gauss to players inventory
public fw_TCannonAddToPlayer( iEnt, Player )
{
	// Prevent run-time errors
	if( is_valid_ent( iEnt ) && is_user_valid_connected( Player ) )
	{
		// Seems that player has picked up a gauss
		if( pev( iEnt, pev_weaponkey ) == GAUSS_WEAPONKEY )
		{
			// Update variable
			g_iHasGauss[ Player ] = true
			
			// Update bp ammo
			cs_set_user_bpammo( Player, CSW_M249, pev( iEnt, pev_bpammo ) )
			
			// Reset weapon options
			set_pev( iEnt, pev_weaponkey, 0 )
			set_pev( iEnt, pev_bpammo, 0 )
			
			return HAM_HANDLED
		}
	}
	return HAM_IGNORED
}

// Gauss post frame
public fw_TCannonPostFrame( iEnt )
{
	// Get owner
	static iOwner
	iOwner = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss?
	if ( g_iHasGauss[ iOwner ] )
	{
		// Reload offset
		static fInReload 
		fInReload = get_pdata_int ( iEnt, m_fInReload,4 )
		
		// Next attack time
		static Float:flNextAttack 
		flNextAttack = get_pdata_float (iOwner, m_flNextAttack, 5 )
		
		// Clip
		static iClip
		iClip = get_pdata_int ( iEnt, m_iClip, 4 )
		
		// Ammo type
		static iAmmoType 
		iAmmoType = m_rgAmmo_player_Slot0 + get_pdata_int ( iEnt, m_iPrimaryAmmoType, 4 )
		
		// BP ammo
		static iBpAmmo
		iBpAmmo = get_pdata_int ( iOwner, iAmmoType, 5 )	
		
		// Reloading
		if ( fInReload && flNextAttack <= 0.0 )
		{
			// Calculate the difference
			static j 
			j = min ( g_pClip - iClip, iBpAmmo )
			
			// Set new clip
			set_pdata_int ( iEnt, m_iClip, iClip + j, 4 )
			
			// Decrease 'x' bullets from backpack(depending on new clip)
			set_pdata_int( iOwner, iAmmoType, iBpAmmo-j, 5 )
			
			// Not reloding anymore
			set_pdata_int ( iEnt, m_fInReload, 0, 4 )
			fInReload = 0
		}
		
		// Get buttons
		static iButton ; iButton = pev ( iOwner, pev_button)
		
		// Attack/Attack2 buttons and next prim/sec attack time hasnt' come yet
		if( ( iButton & IN_ATTACK2 && get_pdata_float ( iEnt, m_flNextSecondaryAttack, 4 ) <= 0.0)
		|| ( iButton & IN_ATTACK && get_pdata_float ( iEnt, m_flNextPrimaryAttack, 4 ) <= 0.0) )
		{
			return
		}
	
		// Reload button / not reloading
		if( iButton & IN_RELOAD && !fInReload )
		{
			// Old clip is more/equal than/to new
			if( iClip >= g_pClip )
			{
				// Remove reload button
				set_pev ( iOwner, pev_button, iButton & ~IN_RELOAD )
				
				// Idle animation
				UTIL_PlayWeaponAnimation ( iOwner, gauss_idle )
				
				// Idle time
				g_flWeaponIdleTime[ iOwner ] = get_gametime( ) + 0.5
			}
			else
			{
				// Out of ammo
				if ( !iBpAmmo )
					return
					
				// Reload weapon
				UTIL_WeaponReload ( iOwner, iEnt )
			}
		}
	}
}

// Gauss reload post
public fw_TCannonReload_Post( iEnt )
{
	// Get owner
	static Player
	Player = get_pdata_cbase( iEnt, m_pPlayer, 4 )
	
	// Does this player has gauss and is he in a middle of reloading ?
	if ( g_iHasGauss[ Player ] && get_pdata_int( iEnt, m_fInReload, 4 ) )
	{
		// Reload
		UTIL_WeaponReload( Player, iEnt )
	}
}

// ------------------------------- Internal Functions ----------------------------------------

// Gauss start fire
public StartFire( Player )
{
	// This var holds damage
	static Float:flDamage
	
	// Make vectors
	UTIL_MakeVectors( Player )
	
	// Get gametime
	static Float:flGameTime
	flGameTime = get_gametime( )
	
	// This is maximal possible damage from secondary attack!
	if( flGameTime - g_flStartCharge[ Player ] > GAUSS_CHARGETIME )
	{
		flDamage = g_pDmgSec
	}
	else
	{
		// The longer you hold attack button - the bigger is damage
		flDamage = g_pDmgSec * ( ( flGameTime - g_flStartCharge[ Player ] ) / GAUSS_CHARGETIME )
	}
	
	// Primary attack do less damage
	if( g_bPrimaryFire[ Player ] )
	{
		flDamage = g_pDmgPrim
	}
	
	// Make sure that we are not ending attack
	if( g_bInAttack[ Player ] != 3 )
	{
		// Secondary attack can pop you up in the air.Not primary attack!
		if( !g_bPrimaryFire[ Player ] )
		{
			// Current players velocity
			static Float:flVel[ 3 ], Float:v_forward[ 3 ]
			pev( Player, pev_velocity, flVel )
			global_get( glb_v_forward, v_forward )
			
			// Try to affect only vertical velocity
			VectorMS( flVel, flDamage * 5.0, v_forward, flVel )
			
			// Jump!
			set_pev( Player, pev_velocity, flVel )
		}
	}
	
	// Recoil
	static Float:flRecoil[ 3 ]
	flRecoil[ 0 ] = GAUSS_RECOIL
	set_pev( Player, pev_punchangle, flRecoil )
	
	// Fire animation
	UTIL_PlayWeaponAnimation( Player, gauss_fire2 )
	
	// Fire sound
	static Float:flResult
	flResult = 0.5 + flDamage * ( 1.0 / 400.0 )
	
	if( flResult > 1.0 )
	{
		flResult = 1.0
	}
	
	emit_sound( Player, CHAN_WEAPON, g_szSoundGaussFire, flResult, ATTN_NORM, 0, 85 + random_num( 0, 0x1f ) )
	
	// Get players aimpoint position
	static Float:vecDest[ 3 ]
	global_get( glb_v_forward, vecDest )
	
	// Calculate start position
	static Float:vecSrc[ 3 ]
	UTIL_GetGunPosition( Player, vecSrc )
	
	// Time until aftershock 'static discharge' sound
	g_fflPlayAfterShock[ Player ] = flGameTime + random_float( 0.3, 0.8 )
	
	// Fire!
	Fire( Player, vecSrc, vecDest, flDamage )
}

// Fire!
Fire( Player, Float:vecOrigSrc[ ], Float:vecDir[ ], Float:flDamage )
{
	// Start position
	static Float:vecSrc[ 3 ]
	xs_vec_copy( vecOrigSrc, vecSrc )
	
	// Calculate end position
	static Float:vecDest[ 3 ]
	VectorMA( vecSrc, 8192.0, vecDir, vecDest )
	
	// Few trace handles
	static tr, beam_tr
	
	// Max fraction
	static Float:flMaxFrac
	flMaxFrac = 1.0
	
	// Total
	static nTotal
	nTotal = 0
	
	// Does this beam punched the wall ?
	static bool:fHasPunched
	fHasPunched = false
	
	// Does this is first beam
	static bool:fFirstBeam
	fFirstBeam = true
	
	// Max hits
	static nMaxHits
	nMaxHits = 10
	
	// Entity whoch should be ignored
	static pEntToIgnore
	
	// Make sure that beam will'be able to cause damage
	while( flDamage > 10 && nMaxHits > 0 )
	{
		// Decrease hit count
		nMaxHits--
		
		// Draw a trace line
		engfunc( EngFunc_TraceLine, vecSrc, vecDest, DONT_IGNORE_MONSTERS, pEntToIgnore, tr )
		
		// We'll never get outside!
		if( get_tr2( tr, TR_AllSolid ) )
			break
		
		// Get entity which was hit
		static pEntity
		pEntity = Instance( get_tr2( tr, TR_pHit ) )	
		
		// Get vector end position
		static Float:vecEnd[ 3 ]
		get_tr2( tr, TR_vecEndPos, vecEnd )
		
		// Its first beam	
		if( fFirstBeam )
		{
			// Add muzzleflash
			set_pev( Player, pev_effects, pev(Player, pev_effects) | EF_MUZZLEFLASH )
			
			// Its not first anymore
			fFirstBeam = false
			
			// Add
			nTotal += 26
			
			// Draw beam
			engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecSrc, 0 )
			//message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
			write_byte( TE_BEAMENTPOINT ) // Temp. entity ID
			write_short( Player | 0x1000 ) // Start entity
			engfunc( EngFunc_WriteCoord, vecEnd[ 0 ] ) // End position X
			engfunc( EngFunc_WriteCoord, vecEnd[ 1 ] ) // End position Y
			engfunc( EngFunc_WriteCoord, vecEnd[ 2 ] ) // End position Z
			write_short( g_iBeam ) // Sprite index
			write_byte( 0 ) // Start frame
			write_byte( 1 ) // Frame rate
			write_byte( 1 ) // Life
			write_byte( g_bPrimaryFire[ Player ] ? 16 : 25 ) // Line width
			write_byte( 0 ) // Noise amplitude
			write_byte( 255 )
			write_byte( 128 )
			write_byte( 0 )
			write_byte( 255 ) // Alpha
			write_byte( 0 ) // Scroll speed
			message_end( )
		}
		else
		{
			// Draw beam
			engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecSrc, 0 )
			write_byte( TE_BEAMPOINTS ) // Temp. entity ID
			engfunc( EngFunc_WriteCoord, vecSrc[ 0 ] ) // Start position X
			engfunc( EngFunc_WriteCoord, vecSrc[ 1 ] ) // Start position Y
			engfunc( EngFunc_WriteCoord, vecSrc[ 2 ] ) // Start position Z
			engfunc( EngFunc_WriteCoord, vecEnd[ 0 ] ) // End position X
			engfunc( EngFunc_WriteCoord, vecEnd[ 1 ] ) // End position Y
			engfunc( EngFunc_WriteCoord, vecEnd[ 2 ] ) // End position Z
			write_short( g_iBeam ) // Sprite index
			write_byte( 0 ) // Start frame
			write_byte( 1 ) // Frame rate
			write_byte( 1 ) // Life
			write_byte( g_bPrimaryFire[ Player ] ? 15 : 25 ) // Line width
			write_byte( 0 ) // Noise amplitude
			write_byte( 255 )
			write_byte( 128 )
			write_byte( 0 )
			write_byte( 255 )
			write_byte( 0 ) // Scroll speed
			message_end( )
		}
		
		// Check if this entity should take any damage
		if( pev( pEntity, pev_takedamage ) != DAMAGE_NO )
		{
			// Check if this is player and zombie
			if( is_user_valid_connected( pEntity )) // Original Code --> if( is_user_valid_connected( pEntity ) && zp_get_user_zombie( pEntity ) )
			{
				// Retrieve health
				static iHealth
				iHealth = get_user_health( pEntity )
			
				// We should be alive
				if( iHealth - flDamage >= 1 )
				{
					// Cause some damage
					ExecuteHamB( Ham_TakeDamage, pEntity, 0, Player, flDamage, DMG_BULLET | DMG_ALWAYSGIB )
				}
				else
				{
					// Die
					g_bKilledByLaser[ pEntity ] = true
					ExecuteHamB( Ham_Killed, pEntity, Player, 2 )
					g_bKilledByLaser[ pEntity ] = false
				}
			}
		}
		
		// Check if this entity should reflect our beam
		if( ReflectGauss( pEntity ) )
		{
			static Float:n
			
			// Return normal vector in a spot we hit
			static Float:vecPlaneNormal[ 3 ]
			get_tr2( tr, TR_vecPlaneNormal, vecPlaneNormal )
			
			// Calculate dot product
			n = - xs_vec_dot( vecPlaneNormal, vecDir )
			
			// 60 degrees
			if ( 0 < n < 0.5 )
			{
				static Float:r[ 3 ]
				VectorMA( vecDir, 2.0 * n, vecPlaneNormal, r )
				
				// Get vector end position
				get_tr2( tr, TR_vecEndPos, vecEnd )
				
				// Get trace fraction
				static Float:trflFraction
				get_tr2( tr, TR_flFraction, trflFraction )
				
				// Calculate fraction
				flMaxFrac = flMaxFrac - trflFraction
				
				// Copy vectors
				xs_vec_copy( r, vecDir )
				
				// Make more vector calculations
				VectorMA( vecEnd, 8.0, vecDir, vecSrc )
				VectorMA( vecSrc, 8192.0, vecDir, vecDest )
			
				// Undone!Do radius damage
				
				// Increase
				nTotal += 34
				
				if( n == 0 )
				{
					// Lose energy
					n = 0.1
				}
				
				// Calculate new damage
				flDamage = flDamage * ( 1 - n )
			}
			else
			{
				// Add gun shot decal on the world
				FX_GunShotDecal( vecEnd, pEntity )
				
				// Add glowing sprite on the world
				FX_TempSprite( vecEnd, 6, floatround( flDamage / 255.0 ) )
				
				// Increase
				nTotal += 13
				
				// Limit it to one hole punch
				if( fHasPunched )
					break
				
				// Update	
				fHasPunched = true	
				
				// Try punching through wall if secondary attack (primary is incapable of 
				// breaking through)
				if( !g_bPrimaryFire[ Player ] )
				{
					// Retrieve vector end position
					get_tr2( tr, TR_vecEndPos, vecEnd )
					
					// Modify start origin
					static Float:vecStart[ 3 ]
					VectorMA( vecEnd, 8.0, vecDir, vecStart )
					
					// Draw another trace line
					engfunc( EngFunc_TraceLine, vecSrc, vecDest, DONT_IGNORE_MONSTERS, pEntToIgnore, beam_tr )
					
					// We'll never get outside
					if( !get_tr2( beam_tr, TR_AllSolid ) )
					{
						// Get end position
						static Float:vecBeamEndPos[ 3 ]
						get_tr2( beam_tr, TR_vecEndPos, vecBeamEndPos )
						
						// Trace backwards to find exit point
						engfunc( EngFunc_TraceLine, vecBeamEndPos, vecEnd, DONT_IGNORE_MONSTERS, pEntToIgnore, beam_tr )
						
						// Again get end position
						get_tr2( beam_tr, TR_vecEndPos, vecBeamEndPos )
						
						static Float:ns, Float:vecSub[ 3 ]
						
						// Subtract vectors
						xs_vec_sub( vecBeamEndPos, vecEnd, vecSub )
						
						// Get vector length
						ns = xs_vec_len( vecSub )
						
						if( ns < flDamage )
						{
							// Lose enery
							if( ns == 0 )
							{
								ns = 1.0
							}
							
							// Decrease damage
							flDamage -= ns
							
							// Subtract
							static Float:vecCalc[ 3 ]
							VectorSubtract( vecEnd, vecDir, vecCalc )
							
							// Absorbtion balls
							FX_SpriteTrail( vecEnd, vecCalc, BALL_AMOUNT, 15, 3, 25, 25 )
							
							// Add gun shot decal on the world
							FX_GunShotDecal( vecBeamEndPos, pEntity )
							
							// And glowing sprite
							FX_TempSprite( vecBeamEndPos, 6, floatround( flDamage / 255.0 ) )
							
							// Subtract
							VectorSubtract( vecBeamEndPos, vecDir, vecCalc )
							
							// Absorbtion balls
							FX_SpriteTrail( vecEnd, vecCalc, BALL_AMOUNT, 15, 3, 25, 25 )
							
							// Increase shit
							nTotal += 21
							
							/*
							// Calculate radius damage
							static Float:flRadDmg
							flRadDmg = flDamage * 1.75
							
							// Undone.Do radius damage here!
							floatradius( flDamage, flRadDmg, vecBeamEndPos )
							*/
							
							// Increase
							nTotal += 53
							
							VectorMA( vecBeamEndPos, 8.0, vecDir, vecSub )
							
							// Add up vector
							xs_vec_add( vecBeamEndPos, vecDir, vecSrc )
						}
					}
					else
					{
						flDamage = 0.0
					}
				}
				else
				{
					// Primary attack
					if( g_bPrimaryFire [ Player ] )
					{
						// Slug doesn't punch through ever with primary 
						// fire, so leave a little glowy bit and make some balls
						FX_TempSprite( vecEnd, 6, floatround( flDamage / 255.0 ) )
						FX_SpriteTrail( vecEnd, vecDir, BALL_AMOUNT, 15, 3, 25, 25 )
					}
					
					flDamage = 0.0
				}
			}
		}
		else
		{
			// Add up vector
			xs_vec_add( vecEnd, vecDir, vecSrc )
			pEntToIgnore = pEntity
		}
	}
}				

// Register and cache CVARs
public Load_Cvars( )
{
	cvar_oneround = register_cvar( "zp_tcannon_oneround", "0" )
	cvar_dmgprim = register_cvar( "zp_tcannon_dmgprim", "200" )
	cvar_dmgsec = register_cvar( "zp_tcannon_dmgsec", "500" )
	cvar_clip = register_cvar( "zp_tcannon_clip", "100" )
	
	g_pOneRound = get_pcvar_num( cvar_oneround )
	g_pDmgPrim = get_pcvar_float( cvar_dmgprim )
	g_pDmgSec = get_pcvar_float( cvar_dmgsec )
	g_pClip = get_pcvar_num( cvar_clip )
}

// Gauss weapon idle
WeaponIdle( Player )
{
	// Get gametime
	static Float:flGameTime
	flGameTime = get_gametime( )
	
	if( g_flWeaponIdleTime[ Player ] > flGameTime )
		return
	
	// Animation sequence variable
	static iAnim
	
	// Animation randomizer
	static Float:flRand
	flRand = random_float( 0.1, 1.0 )
	
	if( flRand <= 0.5 )
	{
		iAnim = gauss_idle
		g_flWeaponIdleTime[ Player ] = flGameTime + random_float( 10.0, 15.0 )
	}
	else if( flRand <= 0.75 )
	{
		iAnim = gauss_idle2
		g_flWeaponIdleTime[ Player ] = flGameTime + random_float( 10.0, 15.0 )
	}
	else
	{
		iAnim = gauss_fidget
		g_flWeaponIdleTime[ Player ] = flGameTime + 3
	}
	
	// Idle
	UTIL_PlayWeaponAnimation( Player, iAnim )
}	

// Play weapon animation
UTIL_PlayWeaponAnimation( const Player, const Sequence )
{
	set_pev( Player, pev_weaponanim, Sequence )
	
	message_begin( MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = Player )
	write_byte( Sequence )
	write_byte( pev( Player, pev_body ) )
	message_end( )
}				

// Make ScreenFade
UTIL_ScreenFade( Player, Duration, HoldTime, Flags, iRed, iGreen, iBlue, iAlpha )
{
	message_begin( MSG_ONE, gmsgScreenFade, _, Player )
	write_short( Duration )
	write_short( HoldTime )
	write_short( Flags )
	write_byte( iRed )
	write_byte( iGreen )
	write_byte( iBlue )
	write_byte( iAlpha )
	message_end( )
}

// Reload gauss
UTIL_WeaponReload( Player, iEnt )
{
	// Modify time until next attack
	set_pdata_float( Player, m_flNextAttack, GAUSS_RELOADTIME+0.5, 5 )
	
	// Reload animation
	UTIL_PlayWeaponAnimation( Player, gauss_spin )
	
	// Enable reload offset
	set_pdata_int( iEnt, m_fInReload, 1, 4 )
	
	// Modify next idle time
	g_flWeaponIdleTime[ Player ] = get_gametime( ) + GAUSS_RELOADTIME + 1.0 
}

// Drop all primary weapons
UTIL_DropPrimary( Player )
{
	// Get user weapons
	static weapons[ 32 ], num, i, weaponid
	num = 0 // reset passed weapons count (bugfix)
	get_user_weapons( Player, weapons, num )
	
	// Loop through them and drop primaries
	for( i = 0; i < num; i++ )
	{
		// Prevent re-indexing the array
		weaponid = weapons[ i ]
		
		// We definetely are holding primary gun
		if(( (1<<weaponid) & PRIMARY_WEAPONS_BITSUM ) )		
		{
			// Get weapon entity
			static wname[32]
			get_weaponname(weaponid, wname, charsmax(wname))
			
			// Player drops the weapon and looses his bpammo
			engclient_cmd( Player, "drop", wname)
		}
	}
}

// Get gun position
UTIL_GetGunPosition( Player, Float:flOrigin[ ] )
{
	static Float:vf_Origin[ 3 ], Float:vf_ViewOfs[ 3 ]
	
	pev( Player, pev_origin, vf_Origin )
	pev( Player, pev_view_ofs, vf_ViewOfs )
	
	xs_vec_add( vf_Origin, vf_ViewOfs, flOrigin )
}

// Make vectors
UTIL_MakeVectors ( Player )
{
	static Float:flAngle[ 3 ], Float:flPunchAngle[ 3 ]

	pev( Player, pev_v_angle, flAngle )
	pev( Player, pev_punchangle, flPunchAngle )

	xs_vec_add( flAngle, flPunchAngle, flAngle )
	engfunc( EngFunc_MakeVectors, flAngle )
}

// From HL SDK.
VectorMA( Float:a[ ], Float:flScale, Float:b[ ], Float:c[ ] )
{
	c[ 0 ] = a[ 0 ] + flScale * b[ 0 ]
	c[ 1 ] = a[ 1 ] + flScale * b[ 1 ]
	c[ 2 ] = a[ 2 ] + flScale * b[ 2 ]
}

VectorMS( const Float:flSource[ ], const Float:flScale, const Float:flMult[ ], Float:flOutput[ ] )
{
        flOutput[ 0 ] = flSource[ 0 ] - flMult[ 0 ] * flScale
        flOutput[ 1 ] = flSource[ 1 ] - flMult[ 1 ] * flScale
        flOutput[ 2 ] = flSource[ 2 ] - flMult[ 2 ] * flScale
}

// Another stuff from HLSDK
Instance( iEnt )
{
	return iEnt == -1 ? 0 : iEnt
}

// Does this entity should refect gauss?
ReflectGauss( iEnt )
{
		return IsBSPModel( iEnt ) && pev( iEnt, pev_takedamage ) == DAMAGE_NO 
}

// Does this entity is BSP model?
IsBSPModel( iEnt )
{
	return pev( iEnt, pev_solid ) == SOLID_BSP || pev( iEnt, pev_movetype ) == MOVETYPE_PUSHSTEP 
}

// Add gun shot decal on world!
FX_GunShotDecal( Float:flPos[ ], pEntity )
{
	// Draw gunshot
	engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flPos, 0 )
	write_byte( TE_GUNSHOTDECAL ) // Temp.entity ID
	engfunc( EngFunc_WriteCoord, flPos[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, flPos[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, flPos[ 2 ] ) // Position Z
	write_short( pEntity ) // Which entity to mark?
	write_byte( 43 ) // Decal number
	message_end( )
}

// Add glow sprite on world
FX_TempSprite( Float:flPos[ ], iScale, iSize )
{
	engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flPos, 0 )
	write_byte( TE_GLOWSPRITE ) // Temp.entity ID
	engfunc( EngFunc_WriteCoord, flPos[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, flPos[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, flPos[ 2 ] ) // Position Z
	write_short( g_iBalls ) // Sprite index
	write_byte( iScale ) // Scale
	write_byte( iSize ) // Size
	write_byte( 255 ) // Brightness
	message_end( )
}

// Add sprite trail
FX_SpriteTrail( Float:vecStart[ ], Float:vecDest[ ], iCount, iLife, iScale, iVel, iRnd )
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_SPRITETRAIL ) // Sprite trail
	engfunc( EngFunc_WriteCoord, vecStart[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, vecStart[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, vecStart[ 2 ] ) // Position Z
	engfunc( EngFunc_WriteCoord, vecDest[ 0 ] ) // Position X
	engfunc( EngFunc_WriteCoord, vecDest[ 1 ] ) // Position Y
	engfunc( EngFunc_WriteCoord, vecDest[ 2 ] ) // Position Z
	write_short( g_iBalls ) // SPrite index
	write_byte( iCount ) // Amount
	write_byte( iLife ) // Life
	write_byte( iScale ) // Scale
	write_byte( iVel ) // Velocity along vector
	write_byte( iRnd ) // Randomness of velocity
	message_end( )
}
Carpex is offline
DJEarthQuake
Veteran Member
Join Date: Jan 2014
Location: Astral planes
Old 05-30-2020 , 00:47   Re: Tau Cannon Help ( pev_owner )
Reply With Quote #4

That is delving pretty deep to pull up that information. Pev owner comment goes back to the tripmine source code. The tripmines won't work on the planter if there is a owner. They are immune to them. How familiar are you with this weapon please? The post leaves me with the impression it is running as designed. The backfiring from over-charging, ricochets, and shooting too close to friends will fry you too.



https://github.com/ValveSoftware/hal...s/tripmine.cpp
edict_t *m_pRealOwner;// tracelines don't hit PEV->OWNER, which means a player couldn't detonate his own trip mine, so we store the owner here.
__________________
DJEarthQuake is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 13:03.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode