Lua Newb needs help

2 Problems

  1. I added 2 sounds, 1 for left click and one for right click and I got it to work by adding another function but I was wondering if I could add both sounds to work into the 1 function that was originally there in the tutorial that I found?

  2. How would I let the player start with the weapon instead of having to spawn it in using the spawn menu. I tried ply:Give(“name”) in various place but it didn’t work


local ShootSound = Sound( "Metal.SawbladeStick" )
local ShootSound2 = Sound("Weapon_Gauss.ChargeLoop")


--
-- Called when the left mouse button is pressed
--
function SWEP:PrimaryAttack()

-- This weapon is 'automatic'. This function call below defines
-- the rate of fire. Here we set it to shoot every 0.5 seconds.
self.Weapon:SetNextPrimaryFire( CurTime() + 0.5 )

-- Call 'ThrowChair' on self with this model
self:ThrowChair( "models/props/cs_office/Chair_office.mdl" )

end


--
-- Called when the rightmouse button is pressed
--
function SWEP:SecondaryAttack()

-- Note we don't call SetNextSecondaryFire here because it's not
-- automatic and so we let them fire as fast as they can click.

-- Call 'ThrowChair' on self with this model
self:ThrowChair2( "models/props_c17/FurnitureChair001a.mdl" )

end

--
-- A custom function we added. When you call this the player will fire a chair!
--
function SWEP:ThrowChair( model_file )

--
-- Play the shoot sound we precached earlier!
--
self:EmitSound( ShootSound )


--
-- If we're the client ) then this is as much as we want to do.
-- We play the sound above on the client due to prediction.
-- ( if ( we didn't they would feel a ping delay during multiplayer )
--
if ( CLIENT ) then return end

--
-- Create a prop_physics entity
--
local ent = ents.Create( "prop_physics" )

--
-- Always make sure that created entities are actually created!
--
if ( !IsValid( ent ) ) then return end

--
-- Set the entity's model to the passed in model
--
ent:SetModel( model_file )

--
-- Set the position to the player's eye position plus 16 units forward.
-- Set the angles to the player'e eye angles. Then spawn it.
--
ent:SetPos( self.Owner:EyePos() + ( self.Owner:GetAimVector() * 20 ) )
ent:SetAngles( self.Owner:EyeAngles() )
ent:Spawn()


--
-- Now get the physics object. Whenever we get a physics object
-- we need to test to make sure its valid before using it.
-- If it isn't ) then we'll remove the entity.
--
local phys = ent:GetPhysicsObject()
if ( !IsValid( phys ) ) then ent:Remove() return end


--
-- Now we apply the force - so the chair actually throws instead
-- of just falling to the ground. You can play with this value here
-- to adjust how fast we throw it.
--
local velocity = self.Owner:GetAimVector()
velocity = velocity * 100
velocity = velocity + ( VectorRand() * 10 ) -- a random element
phys:ApplyForceCenter( velocity )

--
-- Assuming we're playing in Sandbox mode we want to add this
-- entity to the cleanup and undo lists. This is done like so.
--
cleanup.Add( self.Owner, "props", ent )

undo.Create( "Thrown_Chair" )
undo.AddEntity( ent )
undo.SetPlayer( self.Owner )
undo.Finish()

end

Please use [CODE ] tags, it’s really messy to read this…

There

  1. Player:Give( “weapon_physgun” ) for example will give the physgun to the Player object. Player:SelectWeapon( “weapon_physgun” ); forces the player to draw that weapon.

If you’re using a default base, some of them STRIP the weapon if no ammo is given. So if you give a weapon and there is no ammo, or DefaultClip is 0, then you may be getting stripped of the weapon.

Now, for giving the actual item on spawn, it is actually done in PlayerLoadout. So you’d do:


// server/garrysmod/addons/examples/lua/autorun/server/loadout_custom_weapons.lua
hook.Add( "PlayerLoadout", "CustomWeapons", function( _p )
	_p:Give( "weapon_gravgun" );
	_p:Give( "weapon_physgun" );
	_p:SelectWeapon( "weapon_physgun" );
end );

If they still don’t get added, the script is in the wrong spot, or you’re running ULX which rewrites the way hooks run and it is interfering, or you may need to add a timer around the data so it happens after the gamemode function, or PlayerSpawn was edited and didn’t properly re-add PlayerLoadout hook.Call in it.

  1. To play 2 sounds, you can make a table and randomly play them, or use a function and define enumeration for the sound you want to play.

local SoundTable = {
	"path/to/sound.wav";
	"path/to/sound2.wav";
};

// Clientside quick test..
local function PlayMySound( _key )
	local _p = LocalPlayer( );
	local _sound = SoundTable[ _key ];
	if ( _sound ) then
		_p:EmitSound( _sound );
	end
end

PlayMySound( 1 ); -- sound.wav
PlayMySound( 2 ); -- sound2.wav


random


local SoundTable = {
	"path/to/sound.wav";
	"path/to/sound2.wav";
};

// Clientside quick test..
local function PlayMySound( )
	local _p = LocalPlayer( );
	local _sound = table.Random( SoundTable );
	_p:EmitSound( _sound );
end

PlayMySound( ); -- random
PlayMySound( ); -- random


Enumerations


local SOUND1 = 0;
local SOUND2 = 1;

local SoundTable = {
	[ SOUND1 ] = "path/to/sound.wav";
	[ SOUND2 ] = "path/to/sound2.wav";
};

// Clientside quick test..
local function PlayMySound( _enum )
	local _p = LocalPlayer( );
	local _sound = SoundTable[ _enum ];
	if ( _sound ) then
		_p:EmitSound( _sound );
	end
end

PlayMySound( 1 ); -- sound2
PlayMySound( 0 ); -- sound1
PlayMySound( 2 ); -- nothing
PlayMySound( SOUND1 ); -- sound1
PlayMySound( SOUND2 ); -- sound2


Using enumeration helps you create easily readable / identifiable variable names that should never change, they work great for passing numbers through software rather than hard-coding the number and forgetting what that 128 means in a few months time.

Thanks for that, really cleared it up for me. Just one last question, could you simply explain what this does. I have some idea but still unclear.


local function PlayMySound( _enum )
	local _p = LocalPlayer( );
	local _sound = SoundTable[ _enum ];
	if ( _sound ) then
		_p:EmitSound( _sound );

[editline]27th August 2014[/editline]

Sure…

local means that whatever comes after is limited to the scope of what is around it. So for this function, it is for the file it is in. ( You can have a function nested inside of another function which can sometimes be useful for recursive functions that need certain checks in more than one place…

So, we create a local to the file function called PlayMySound that takes 1 argument _enum ( variable name can be anything you want it to be as long as it doesn’t start with a number or contain special characters ).
local function PlayMySound( _enum )

Here, I define LocalPlayer( ); to the variable _p so I can reference it without having to type LocalPlayer( ) out each time I want to call it. Typically right after that declaration an IsValid check is called to ensure the player is fully in the game. This is also a local ( this time local to the inside of the function so nothing outside of the function knows about it )
local _p = LocalPlayer( );

Alright, so this… We’re taking a value from the table SoundTable located at a specific spot in the list. We reference this specific spot with the argument that is passed in to the function. So, if you pass in SOUND1 or SOUND2, it’ll essentially be the same as passing in 0 or 1 but with a user-friendly name. So, once the table knows the value, the value then gets passed back to _sound so we can reference it at another point in the script
local _sound = SoundTable[ _enum ];

And that point is here. This is a simple check to ensure that the variable is set. The only way for this to “fail” is if the expression ( _sound ) returns “false” or “nil”.
if ( _sound ) then

If _sound is defined as something usable, we continue here. So, EmitSound is a function that exists within the Player Meta-table. Metatables are tables that act as a template which can be cloned as many times as needed and can react to math functions being used on them, to string methods, call which lets the table act like a function, and more. It can actually be called many different ways, I’ll type those up. But, this is like saying LocalPlayer( ):EmitSound( “path/to/sound.wav” ), but LocalPlayer( ) is assigned to _p, and “path/to/sound.wav” is assigned to _sound by way of using the enumeration / key to obtain the value, and EmitSound will play a sound ( and move the players lips ).
_p:EmitSound( _sound );

The call can be written many different ways.

Using the actual values: LocalPlayer( ):EmitSound( “path/to/sound.wav” )
Using the short-hand based on vars we defined: _p:EmitSound( _sound );
By accessing the function through a . ( which doesn’t infer self meaning it needs to be passed in as the first argument: _p.EmitSound( self, _sound );
etc…

All of them are essentially identical.