Garry's Mod Wiki

Revision Difference

Chair_Throwing_Gun#528275

<cat>Dev.Lua</cat> # Introduction In this tutorial we will create a weapon that fires chairs. # File Layout * Open your garry's mod folder. * Open the 'addons' folder. * Create a folder called 'chairlauncher' * Create a folder inside called 'lua' * Create a folder inside called 'weapons' * Create a file called 'weapon_chairgun.lua' Your folder structure should be like this: ``` garrysmod/addons/chairlauncher/lua/weapons/weapon_chairgun.lua ``` You have created an addon called **chairlauncher** which contains a weapon called **weapon_chairgun**. Whenever you create a new weapon, most people use the **weapon_** prefix, since most of the default weapons names also start with **weapon_**. # The Code Add these to your weapon after you understand them. ## Informational This code is just informational. It shows up in the spawnmenu and the weapon selection menu.. so it will help people out if your weapon is complicated to use. You can also put your name in the author field so people know who made it. ``` SWEP.PrintName = "Chair Thrower" -- This will be shown in the spawn menu, and in the weapon selection menu SWEP.Author = "(your name)" -- These two options will be shown when you have the weapon highlighted in the weapon selection menu SWEP.Instructions = "Left mouse to fire a chair!" ``` ## Spawn Info Defines whether players can spawn this weapon from the spawnmenu.. and whether only admins can spawn it. ``` SWEP.Spawnable = true SWEP.AdminOnly = true ``` ## Clip Info Our weapon doesn't use any ammo or clips, so we just set the clip sizes to -1 and the ammo to "none". We set primary to be automatic. This means that the player doesn't have to release the mouse button and press it again - it will continually fire. ``` SWEP.Primary.ClipSize = -1 SWEP.Primary.DefaultClip = -1 SWEP.Primary.Automatic = true SWEP.Primary.Ammo = "none" SWEP.Secondary.ClipSize = -1 SWEP.Secondary.DefaultClip = -1 SWEP.Secondary.Automatic = false SWEP.Secondary.Ammo = "none" ``` ## More Info These are mostly self explanatory. The higher the weight the more likely you are to switch to it. Slot and SlotPos decide where in your weapon menu the weapon will be. ``` SWEP.Weight = 5 SWEP.AutoSwitchTo = false SWEP.AutoSwitchFrom = false SWEP.Slot = 1 SWEP.SlotPos = 2 SWEP.DrawAmmo = false SWEP.DrawCrosshair = true ``` ## Models The view-model and the world-model to use. ``` SWEP.ViewModel = "models/weapons/v_pistol.mdl" SWEP.WorldModel = "models/weapons/w_pistol.mdl" ``` ## Precache Sounds You can precache sounds by defining them as locals using the Sound function. This prevents the sound loading when you first shoot the weapon - causing a hitch. You can precache sounds by defining them as locals or SWEP variables using the Sound function. This prevents the sound loading when you first shoot the weapon - causing a hitch. ``` local ShootSound = Sound( "Metal.SawbladeStick" ) SWEP.ShootSound = Sound( "Metal.SawbladeStick" ) ``` ## The actual chair throwing code Commented for your learning pleasure ``` --⤶ -- Called when the left mouse button is pressed --⤶ function SWEP:PrimaryAttack() -- This weapon is 'automatic'. This function call below defines -- 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 ) self:SetNextPrimaryFire( CurTime() + 0.5 ) -- Call 'ThrowChair' on self with this model self:ThrowChair( "models/props/cs_office/Chair_office.mdl" ) ⤶ end⤶ end⤶ ⤶ --⤶ -- Called when the rightmouse button is pressed⤶ --⤶ ⤶ -- 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:ThrowChair( "models/props_c17/FurnitureChair001a.mdl" ) ⤶ end⤶ ⤶ --⤶ -- A custom function we added. When you call this the player will fire a chair!⤶ --⤶ -- Though the secondary fire isn't automatic⤶ -- players shouldn't be able to fire too fast⤶ self:SetNextSecondaryFire( CurTime() + 0.1 )⤶ self:ThrowChair( "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 ) --⤶ local owner = self:GetOwner() -- Make sure the weapon is being held before trying to throw a chair⤶ if ( not owner:IsValid() ) then return end⤶ ⤶ -- Play the shoot sound we precached earlier! self:EmitSound( self.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⤶ --⤶ -- 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⤶ --⤶ -- Always make sure that created entities are actually created!⤶ if ( not ent:IsValid() ) 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() * 16) )⤶ ent:SetAngles( self.Owner:EyeAngles() )⤶ ⤶ -- This is the same as owner:EyePos() + (self.Owner:GetAimVector() * 16) -- but the vector methods prevent duplicitous objects from being created⤶ -- which is faster and more memory efficient⤶ -- AimVector is not directly modified as it is used again later in the function⤶ local aimvec = owner:GetAimVector()⤶ local pos = aimvec * 16 -- This creates a new vector object⤶ pos:Add( owner:EyePos() ) -- This translates the local aimvector to world coordinates⤶ ⤶ -- Set the position to the player's eye position plus 16 units forward.⤶ ent:SetPos( pos )⤶ ⤶ -- Set the angles to the player'e eye angles. Then spawn it.⤶ ent:SetAngles( 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 if ( not phys:IsValid() ) 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 ) -- Now that this is the last use of the aimvector vector we created,⤶ -- we can directly modify it instead of creating another copy⤶ aimvec:Mul( 100 ) aimvec:Add( VectorRand( -10, 10 ) ) -- Add a random vector with elements [-10, 10)⤶ phys:ApplyForceCenter( aimvec ) --⤶ -- 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 )⤶ cleanup.Add( owner, "props", ent )⤶ undo.Create( "Thrown_Chair" ) undo.AddEntity( ent ) undo.SetPlayer( self.Owner ) undo.SetPlayer( owner ) undo.Finish() end ``` # Challenges Can you edit the new weapon to: * Use a different firing sound for left/right click * Throw a melon when you press reload? (tip: <page>WEAPON:Reload</page>) * Throw 3 chairs at a time