• Help, please? Lua Weapon is not playing my sound!
    41 replies, posted
[QUOTE=_Kilburn;40180172]You're so god damn uncooperative I'm not even sure I should be spending my time trying to help you. No one cares about your personal life, now send me your code already. By private message if you're really so scared of people stealing it. It's not like you're going to risk leaking 2 years worth of hard work.[/QUOTE] No shit, why the fuck do you think I said "STOP IT?" I said this: [QUOTE=luavirusfree;40176015][highlight]But enough of this, please? I didn't bring that to the table to change the topic of this thread, back on topic, please? Thank you.[/highlight][/QUOTE] So lets just fucking drop it, already? I'm about to post the modern code, it's only two files, the base (Shared.lua) and the weapon (Shared.lua) Here is the Main swep: [lua]AddCSLuaFile() if CLIENT then SWEP.Category = "Chambering Sweps" SWEP.PrintName = "Pulse Minigun v0.8.2" -- v0.8.2 : Version 0, sub type 8, revision 2. v1.0.0 doesn't have the secondary explosive attack. SWEP.Slot = 4 SWEP.SlotPos = 1 SWEP.DrawAmmo = true SWEP.DrawCrosshair = true SWEP.HoldType = "ar2" language.Add( "HeliCharge_ammo", "R.E. Pulse Core" ) -- Ammunition name! end if SERVER then SWEP.Weight = 5 SWEP.AutoSwitchTo = true SWEP.AutoSwitchFrom = true SWEP.HoldType = "ar2" end -- TODO! TODO! TODO! GET THE RECHARGE SOUND WORKING!!! TODO! TODO! TODO! -- --[[ game.AddAmmoType( { name = "HeliCharge", dmgtype = bit.bor(DMG_AIRBOAT, DMG_ALWAYSGIB), -- Hurt helicopters! ALWAYSGIB doesn't seem to do anything in my tests. tracer = 4, -- 0 - None, 1 - Line, 2 - Rail, 3 - Beam, 4 - Line and Whiz. Some tracer types only work with some values. plydmg = 5, npcdmg = 4, force = 5, minsplash = 3, maxsplash = 4 } ) ]] SWEP.Author = "LuaVirusFree" SWEP.Contact = "5kyl3r469@gmail.com" SWEP.Purpose = "Demonstrate percent display mode. This is the Helicopter's Gun!" SWEP.Instructions = "Primary shoots." SWEP.Spawnable = true SWEP.AdminSpawnable = true SWEP.ViewModel = "models/weapons/v_irifle.mdl" -- TODO: Get a view model of the airboat's gun? SWEP.WorldModel = "models/weapons/w_irifle.mdl" SWEP.ViewModelFOV = 54 SWEP.Primary.ClipSize = 100 SWEP.Primary.DefaultClip = 37 SWEP.Primary.Automatic = true SWEP.Primary.Ammo = "HelicopterGun" SWEP.Secondary.ClipSize = -1 SWEP.Secondary.DefaultClip = -1 SWEP.Secondary.Automatic = false SWEP.Secondary.Ammo = "none" SWEP.HoldType = "ar2" SWEP.ActualAmmo = 105 SWEP.Base = "base_rc" -- Organized roughly by use. SWEP.Burrets = 2 -- How many bullets are fired in one shot? SWEP.ShotsTaken = 1 -- The number of rounds one shot will take from the magazine. SWEP.Primary.Delay = 0.05 SWEP.Spread = 0.20 -- How far can our bullet go away from straight? This should be the Helicopter's setting, by default anyways. SWEP.BurretForce = 35 -- How much force is put on physics objects we hit. SWEP.DMGMin = 4 -- The minimum damage one bullet can do. SWEP.DMGMax = 5 -- The maximum damage one bullet can do. SWEP.Primary.Recoil = 2.5 -- How far the screen will move when we shoot. This weapon is very powerful, so very far! SWEP.Tracenum = 1 -- On every X shot we will show tracers. 1 is always, 2 is every other shot, etc. SWEP.Tracer = "AR2Tracer" -- Like the HelicopterTracer, but a little thinner. -- HelicopterTracer (W) AR2Tracer (W) GaussTracer (DW) GunshipTracer (DW) AirboatGunTracer (W) StriderTracer (DW) Tracer (W) LaserTracer (DW) ToolTracer (W) -- Above are all of the tracer options I know of... SWEP.CanSwitch = false -- Can we change our fire mode? true = semi and auto, false = only whatever SWEP.Primary.Automaticc says. It is changed with secondary fire if this is true. SWEP.NoChamberRound = true -- Weapons that load like the 357 usually don't have chambers. The 357 does not have a chamber... the chamber is the same thing you load into. SWEP.NoORS = true --SWEP.ShootSound = Sound( "Weapon_AR2.NPC_Single" ) -- The sound played when we shoot. SWEP.ShootSound = Sound( "Airboat.FireGunHeavy" ) SWEP.EmptySound = Sound( "Weapon_AR2.Empty" ) -- The sound played when we try to fire, but have no ammunition to shoot. SWEP.FiringLoop = Sound( "NPC_AttackHelicopter.FireGun" ) -- TODO: Find out how to loop this sound as long as IN_ATTACK is down! SWEP.FiringEnd = nil -- Sound( "NPC_AttackHelicopter.ChargeDownGun" ) -- When we stop firing, we rev down. This seems to be an empty sound, however. SWEP.ChargeSound = Sound( "NPC_Strider.Charge" ) -- Silent sound. Silent, but no longer deadly! SWEP.RechargeSound = Sound( "NPC_AttackHelicopter.ChargeGun" ) -- Reloading! SWEP.LSound = nil -- Create the sound's variable. SWEP.CSound = nil -- Create the charging sound's variable. --SWEP.RCSound = nil SWEP.Shot1 = false SWEP.DoCrits=false SWEP.CritMax = 6 -- One in 6 chance of crit, very common! SWEP.CritVar = 3 SWEP.CritScale = 9 -- Instantly kill a Antlion Guardian if we critical. SWEP.ReloadDone = CurTime() SWEP.JustStop = false SWEP.CurClip = 0 SWEP.FirstShot = true SWEP.IsCharging = false SWEP.ChargeStart = CurTime() SWEP.ChargeLVL = 0 function SWEP:Initialize() self.DefaultClipSize = self.Primary.ClipSize -- When we initialize, our clip size is our original clip size we were set to! Let's save that. self:SetClip1( math.floor( ( self.ActualAmmo / 105 ) * 100 ) ) -- One you only have one shot left it will say 0. If it says 0, you can't shoot. This makes it 170 even. self.LSound = CreateSound( self, self.FiringLoop ) -- Let's create the sound we play when we are shooting) self.CSound = CreateSound( self, self.ChargeSound ) -- Let's create the sound we play when we are shooting) -- self.RCSound = CreateSound( self, self.RechargeSound ) self:SetWeaponHoldType( "ar2" ) end SWEP.Recharging = false SWEP.NextCharge = CurTime() function SWEP:Think() if self:Clip1() == 0 then self.Primary.Delay = 0.777 else self.Primary.Delay = 0.05 end if CurTime() >= self.ReloadDone && !self.FirstShot then self.FirstShot=true end if !self.Owner:KeyDown( IN_ATTACK ) then self.LSound:Stop() end if !self.Owner:KeyDown( IN_ATTACK ) && self.JustStop then self.JustStop = false; if self:IsValid() then self:Reload() end end if !self.Owner:KeyDown( IN_ATTACK2 ) then self.CSound:Stop(); self.IsCharging = false end if self.ActualAmmo <= 2 then if self:IsValid() then self:Reload() end end -- We are empty, so we should reload! TODO: Charge over time otherwise! if self.ChargeLVL >= 0.8 or CurTime() > (self.ChargeStart+1.2) then self:FireExplosive() end if self.Owner:KeyDown( IN_ATTACK ) then self.Recharging = false end if self.Owner:KeyDown( IN_ATTACK2 ) && self.ActualAmmo >= 105 then self.Recharging = false end if !self.Owner:KeyDown( bit.bor( IN_ATTACK, IN_ATTACK2 ) ) && self.ActualAmmo < 105 then if self:IsValid() then self:Reload() end end if self.Recharging && CurTime() >= self.NextCharge && self.ActualAmmo < 105 then if !self.PlayedSound then if CLIENT then self:EmitSound( self.RechargeSound ); print("test") end self.PlayedSound = true end self.ActualAmmo = self.ActualAmmo + 1 if self.ActualAmmo < 105 then self.NextCharge = CurTime() + 0.02 end self:SetClip1( math.floor( ( self.ActualAmmo / 105 ) * 100 ) ) end if self:Clip1() >= 100 or self.Owner:KeyDown( IN_ATTACK ) then self.Recharging = false if CLIENT then self:StopSound( self.RechargeSound ) -- print("test off") end end end SWEP.PlayedSound = false function SWEP:Reload() if self.Recharging then return end if !self.Owner:KeyDown( bit.bor( IN_ATTACK, IN_ATTACK2 ) ) then if !self.Recharging then self.Recharging = true self.NextCharge = CurTime() self.PlayedSound = false if CLIENT then self:EmitSound( self.RechargeSound ) end end else self.Recharging = false end end function SWEP:PrimaryAttack() if self:Clip1() == 0 or !self:CanPrimaryAttack() then self.Primary.Delay = 0.777 else self.Primary.Delay = 0.05 end if self.Owner:KeyDown( IN_ATTACK2 ) then return end -- We are secondary attacking... so we can't primary atta
Okay, so first of all weapon sounds should be played from both the client and the server. Remove the "if CLIENT" checks around your self:EmitSound calls. Secondly, I noticed that you keep stopping the sound when the weapon is full. That seems to be the reason why your reloading sound sometimes doesn't play. This is your code: [lua] if self:Clip1() >= 100 or self.Owner:KeyDown( IN_ATTACK ) then self.Recharging = false if CLIENT then self:StopSound( self.RechargeSound ) -- print("test off") end end[/lua] I changed it to this: [lua] if self:Clip1() >= 100 or self.Owner:KeyDown( IN_ATTACK ) then self.Recharging = false if self.PlayedSound then self:StopSound( self.RechargeSound ) self.PlayedSound = false end end[/lua] That works on my side. It ensures that the weapon will only attempt to stop the reloading sound if it has been played.
Well, thanks I will try that, but I want to stop the sound when the weapon is full! -_- because if your ammo is full, or you start firing anyways, well... you're not charging anymore, are you? Just like the AirBoat gun and the Helicopter's Gun.
[QUOTE=luavirusfree;40189393]Well, thanks I will try that, but I want to stop the sound when the weapon is full! -_- because if your ammo is full, or you start firing anyways, well... you're not charging anymore, are you? Just like the AirBoat gun and the Helicopter's Gun.[/QUOTE] But that's what it does already? I just made your weapon stop the reloading sound only when necessary, rather than stopping it all the time even if it's not playing.
[QUOTE=_Kilburn;40192684]But that's what it does already? I just made your weapon stop the reloading sound only when necessary, rather than stopping it all the time even if it's not playing.[/QUOTE] Oh, and btw, which version did you use? The code has changed a lot in the weeks this thread has been here. [editline]7th April 2013[/editline] [video=youtube_share;F5odWw86Opw]http://youtu.be/F5odWw86Opw[/video] [URL]http://youtu.be/F5odWw86Opw[/URL] Okay, fuck, I've got it now, thank you!!!!! It's just too quiet. I'm not editing, the lua tag will be destroyed or if I put it back in and all of the text will be treated as if it's on the same line... I've been made aware that this won't work on Multiplayer, it will become desynchronized between the clients and the server. While that doesn't affect me since my laptop has gone to shit, probably with spyware and shit like that, not viruses... I still would like to know how I could make variables that will stay synchronized 100% at all times between the Clients and the Server.
Well, hey, sorry for the double post, what do you think of this: The AirBoat's Gun charges up from the AirBoat's Engine, so why not make the player-useable version feed off of the Player's Suit Charge? As for allowing it to be recharged by the weapon, I don't know about that... thoughts? [editline]7th April 2013[/editline] Also, I've been made aware that this won't work on Multiplayer, it will become desynchronized between the clients and the server. While that doesn't affect me since my laptop has gone to shit, probably with spyware and shit like that, not viruses... I still would like to know how I could make variables that will stay synchronized 100% at all times between the Clients and the Server. I made this weapon for two things: a swep collection and a campaign gamemode ( an easter egg ).
[QUOTE=luavirusfree;40201376]Well, hey, sorry for the double post, what do you think of this: The AirBoat's Gun charges up from the AirBoat's Engine, so why not make the player-useable version feed off of the Player's Suit Charge? As for allowing it to be recharged by the weapon, I don't know about that... thoughts?[/QUOTE] Depends on the importance of suit charge in your gamemode, and whether you want your weapon to be balanced or not. Although I think it would make more sense to have your weapon use its own "ammo". [QUOTE=luavirusfree;40201376]Also, I've been made aware that this won't work on Multiplayer, it will become desynchronized between the clients and the server. While that doesn't affect me since my laptop has gone to shit, probably with spyware and shit like that, not viruses... I still would like to know how I could make variables that will stay synchronized 100% at all times between the Clients and the Server.[/QUOTE] First of all stop storing the weapon's real ammo in a separate variable. You're basically overriding the weapon's ammo just because you want it to display a percentage. That's incredibly tedious and it will generate way too many issues to be worth it. It would be way better to hide the ammo counter and draw your own, or even use the [url=http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/indexd137.html]CustomAmmoDisplay[/url] hook if you're lazy. If you still need variables that are properly synced between the server and the client, the first thing you'll want to use is [url=http://wiki.garrysmod.com/page/Networking_Entities]datatable variables[/url]. That link describes how to set them up on scripted entities but it works just the same for scripted weapons. They are basically variables that are automatically updated on the client when you set them on the server. If there is a variable that you are using on both the client and the server, it [b]should[/b] be a datatable variable, and you should update it on both the client and the server. That will make sure your weapon is probably synced between the client and the server. Datatable variables come in a very limited amount though so you should use them carefully. Not everything has to be synced between the client and the server. Here's also a small wall of text that I initially typed, although I figured it might be unnecessarily complicated. I still left it there just in case you want to get some technical details on how weapons work. [quote] You'll also need to understand the concept of prediction. Basically when you're firing your weapon while on a multiplayer server, it immediately calls the PrimaryAttack function on your client's side. That lets your computer do all the visual and sound effects even though the server itself doesn't even know that you fired yet. Without this, you would only see yourself firing your weapon after a small delay, depending on your ping. A bit later (again, depending on your ping), the server receives a message telling it that you fired your weapon. That calls the PrimaryAttack function on the server's side, playing sounds that everyone can hear, firing bullets that actually damage people, changing the state of the weapon and sending the new state to your client (the state being ammo, animation, next firing time, and eventually anything you might have defined using datatable variables). Once your computer receives that updated status back, it will call PrimaryAttack (clientside) multiple times to perform some smoothing between the state it predicted on its own side and the state returned by the server. This is why you should be really careful about what to make serverside only or clientside only. A lot of functions behave differently when used in weapon hooks, for instance calling EmitSound serverside will play a sound that everyone can hear except the owner of the weapon. That's because the client side should take care of that. Same goes for the bullet tracer effect generated by FireBullets. All of this hidden behaviour is mostly transparent but you should be aware of it before isolating parts of your code between "if CLIENT then" or "if SERVER then" checks. Note that datatable variables are also subject to prediction, meaning you should update them on both the client and the server when used in weapons. When you modify a datatable variable clientside, it will retain the modified value until the server updates it. As a matter of fact, SetClip1, SetClip2, SetNextPrimaryFire and SetNextSecondaryFire all access internal datatable variables. [/quote] Also, another thing. Weapons behave differently in singleplayer, on a listen server and on a dedicated server. In singleplayer, there is no prediction so most weapon hooks are called serverside only. On a listen server, there is no prediction on the host, they will perceive the game as if they were in a singleplayer game. However, players who connect to the server will use prediction, so they will perceive things differently from the host. On a dedicated server, there's no host player, so everyone uses prediction. That's why a dedicated server is probably the best way to test whether your weapon is properly networked or not. And one last thing: use lag compensation. You do that by calling self.Owner:LagCompensation(true) right before performing a trace or calling FireBullets, and self.Owner:LagCompensation(false) right after. Lag compensation basically moves every player back in time when turned on, and then back to their original position when turned off. That's why you never leave it on. It is useful because it helps you land your shots even with a large ping. Without it, you would have to aim where a player will be in order to actually hit them. That's because when you fire your weapon at a player, their position on your computer is actually their position on the server at some time in the past, since the server hasn't sent you their new position yet. That's why you move them back in time on the server, so their position on the server temporarily matches their position on your computer.
Well, I only really intend for this weapon to be used in singleplayer, for multiplayer I would also need to make the thing respawn every so often, just so other players can get it. (true for all weapons, really). That means I'd also need a way to prevent the player from picking it up as ammo. BTW... my computer can no longer connect to servers -_- i don't know why, but the game usually crashes or freezes when I try to, or it does its thing then goes straight back to the main menu when I'm done connecting. [editline]8th April 2013[/editline] Also, the last time I used the example they give for CustomAmmoDisplay ... it basically informed me via the console that the self:Clip1() and self:Clip2() functions couldn't be called there... [editline]8th April 2013[/editline] How do I check if the player is in Single Player mode? I don't want lag compensation if they are. [editline]8th April 2013[/editline] Also, if lag compensation only affects the player that fired, then... you'd still get that problem, since you see... whomever they were aiming at didn't get lag compensated, so they still could've moved forward after you fired.
[QUOTE=luavirusfree;40206423]Well, I only really intend for this weapon to be used in singleplayer, for multiplayer I would also need to make the thing respawn every so often, just so other players can get it. (true for all weapons, really). That means I'd also need a way to prevent the player from picking it up as ammo. BTW... my computer can no longer connect to servers -_- i don't know why, but the game usually crashes or freezes when I try to, or it does its thing then goes straight back to the main menu when I'm done connecting.[/QUOTE] Well that's going to be more gamemode coding than weapon coding. Making a weapon respawn would be as simple as storing the initial position of every weapon when the map starts and respawning a weapon a given amount of time after it has been picked up. As for preventing players from collecting weapons for ammo, you can use [url=http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/index3789.html]PlayerCanPickupWeapon[/url]. If your game has issues, maybe you can try reinstalling it? [QUOTE=luavirusfree;40206423] Also, the last time I used the example they give for CustomAmmoDisplay ... it basically informed me via the console that the self:Clip1() and self:Clip2() functions couldn't be called there... [/QUOTE] I had a look at it... looks like Garry broke it. For some reason, the "self" passed to CustomAmmoDisplay isn't the weapon at all, it's its metatable. I'll report that to Garry, that's probably not how it's supposed to work. In the meantime you can add this at the beginning of CustomAmmoDisplay: [lua]self = LocalPlayer():GetActiveWeapon()[/lua] This will always work because it's a clientside function that only concerns the local player, as in, you. And it only gets called when you have that weapon out. [QUOTE=luavirusfree;40206423] How do I check if the player is in Single Player mode? I don't want lag compensation if they are. [/QUOTE] [url=http://wiki.garrysmod.com/page/game/SinglePlayer]game.SinglePlayer[/url] As for dedicated servers: [url=http://wiki.garrysmod.com/page/game/IsDedicated]game.IsDedicated[/url] If it's neither singleplayer, nor a dedicated server, then it's a listen server. However you don't need to make it so lag compensation doesn't happen in singleplayer, because it does nothing in singleplayer anyway. [QUOTE=luavirusfree;40206423] Also, if lag compensation only affects the player that fired, then... you'd still get that problem, since you see... whomever they were aiming at didn't get lag compensated, so they still could've moved forward after you fired.[/QUOTE] Actually it affects every player except the player who fired. When you do self.Owner:LagCompensation(true), it will move every player on the server except self.Owner back in time. Then, when you do self.Owner:LagCompensation(false), it moves them back to their original position. Since this is all done instantly, there is no actual visible movement, so no one notices it. That's also why you can get sniped by a player with a high ping in Source games even though you already took cover behind a corner.
If it's a clientside function, won't that mess it upon the server side?
[QUOTE=luavirusfree;40211024]If it's a clientside function, won't that mess it upon the server side?[/QUOTE] Why would it? [editline]9th April 2013[/editline] If you still don't understand the whole client/server thing, the best example would be a dedicated server. A dedicated server is a computer that runs only the serverside version of the game. It only takes care of the game logic and doesn't have a display. When you connect to it using your own computer, your computer becomes a client, and runs only the clientside version of the game, along with the clientside Lua files the server sent to you. That's why you need AddCSLuaFile, it's basically a serverside function that tells the server which clientside files should be sent to clients. So basically, serverside code and clientside code are completely independent from each other, because they are two completely different scripts that run on different computers. Shared code is simply a convenience for not having to write the same code on the client and the server. That's useful for prediction, when you want the client to simulate what should happen on the server. This is why most weapons contain mostly shared code, they are strongly subject to prediction. CustomAmmoDisplay can be defined on the server but it will be never called, since it's a clientside only hook. However if you want to be consistent, you can isolate it inside a "if CLIENT then" check. Like this: [lua]if CLIENT then function SWEP:CustomAmmoDisplay() end end[/lua] This way it will be only defined clientside.
[QUOTE=_Kilburn;40215843]Why would it? [editline]9th April 2013[/editline] If you still don't understand the whole client/server thing, the best example would be a dedicated server. A dedicated server is a computer that runs only the serverside version of the game. It only takes care of the game logic and doesn't have a display. When you connect to it using your own computer, your computer becomes a client, and runs only the clientside version of the game, along with the clientside Lua files the server sent to you. That's why you need AddCSLuaFile, it's basically a serverside function that tells the server which clientside files should be sent to clients. So basically, serverside code and clientside code are completely independent from each other, because they are two completely different scripts that run on different computers. Shared code is simply a convenience for not having to write the same code on the client and the server. That's useful for prediction, when you want the client to simulate what should happen on the server. This is why most weapons contain mostly shared code, they are strongly subject to prediction. CustomAmmoDisplay can be defined on the server but it will be never called, since it's a clientside only hook. However if you want to be consistent, you can isolate it inside a "if CLIENT then" check. Like this: [lua]if CLIENT then function SWEP:CustomAmmoDisplay() end end[/lua] This way it will be only defined clientside.[/QUOTE] Please pardon the bump. I already knew the differences between it. But I believe I do not know that calling clientside code on one client, the owner, would update it for ALL clients... [editline]9th May 2013[/editline] It doesn't matter for me since I only made it for single-player use... [editline]9th May 2013[/editline] But it may matter in the future. Sorry if this double posts, I looked and if I would've just edited, the code tag would've disappeared, which would cause other problems once I re-submitted.
Sorry, you need to Log In to post a reply to this thread.