I am designing a weapon which should occasionally - but not always - set its target on fire. How do I code the weapon so that each bullet has, say, a 15% chance of setting something ablaze?
I'm not exactle sure, but I would guess somthing like
[code]
<shooting function here>
RandomNumber = math.random(1,100)
if RandomNumber < 16 then
<inset burning bullet here>
else
<inset std. bullet here>
end
end
[/code]
I'm very new with lua, but I think you get the idea.
Thanks very much, this helps. I will try it.
[editline]11:58PM[/editline]
Okay, I've put it in (after a fashion) and moved things around until I've boiled my error message down to:
<eof> expected near "else"
This is the code in question:
[lua]
//SWEP:PrimaryFire()\\
function SWEP:PrimaryAttack()
RandomNumber = math.random(1,100)
if RandomNumber > 15 then
local bullet = {}
bullet.Num = self.Primary.NumberofShots
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector( self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
bullet.Tracer = 1
bullet.Force = self.Primary.Force
bullet.Damage = self.Primary.Damage
bullet.AmmoType = self.Primary.Ammo
if ( !self:CanPrimaryAttack() ) then return end
local rnda = self.Primary.Recoil * -1
local rndb = self.Primary.Recoil * math.random(-1, 1)
self:ShootEffects()
self.Owner:FireBullets( bullet )
self.Weapon:EmitSound(Sound(self.Primary.Sound))
self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )
self:TakePrimaryAmmo(self.Primary.TakeAmmo)
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay )
end
end
else
local bullet = {}
bullet.Num = self.Primary.NumberofShots
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector( self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
bullet.Tracer = 1
bullet.Force = self.Primary.Force
bullet.Damage = self.Primary.Damage
bullet.AmmoType = self.Primary.Ammo
bullet.Callback = function(attacker,tr,dmginfo)
if tr.Entity:IsValid() then tr.Entity:Ignite(20,30) return end
if ( !self:CanPrimaryAttack() ) then return end
local rnda = self.Primary.Recoil * -1
local rndb = self.Primary.Recoil * math.random(-1, 1)
self:ShootEffects()
self.Owner:FireBullets( bullet )
self.Weapon:EmitSound(Sound(self.Primary.Sound))
self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )
self:TakePrimaryAmmo(self.Primary.TakeAmmo)
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay )
end
end
//SWEP:PrimaryFire()\\
[/lua]
Any ideas?
Put it in lua tags so we can see the indentation, that looks horrendous.
[lua]function SWEP:PrimaryAttack()
RandomNumber = math.random(1,100)
if RandomNumber > 15 then
local bullet = {}
bullet.Num = self.Primary.NumberofShots
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector( self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
bullet.Tracer = 1
bullet.Force = self.Primary.Force
bullet.Damage = self.Primary.Damage
bullet.AmmoType = self.Primary.Ammo
if ( !self:CanPrimaryAttack() ) then return end
local rnda = self.Primary.Recoil * -1
local rndb = self.Primary.Recoil * math.random(-1, 1)
self:ShootEffects()
self.Owner:FireBullets( bullet )
self.Weapon:EmitSound(Sound(self.Primary.Sound))
self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )
self:TakePrimaryAmmo(self.Primary.TakeAmmo)
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay )
end
end
else
local bullet = {}
bullet.Num = self.Primary.NumberofShots
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector( self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
bullet.Tracer = 1
bullet.Force = self.Primary.Force
bullet.Damage = self.Primary.Damage
bullet.AmmoType = self.Primary.Ammo
bullet.Callback = function(attacker,tr,dmginfo)
if tr.Entity:IsValid() then tr.Entity:Ignite(20,30) return end
if ( !self:CanPrimaryAttack() ) then return end
local rnda = self.Primary.Recoil * -1
local rndb = self.Primary.Recoil * math.random(-1, 1)
self:ShootEffects()
self.Owner:FireBullets( bullet )
self.Weapon:EmitSound(Sound(self.Primary.Sound))
self.Owner:ViewPunch( Angle( rnda,rndb,rnda ) )
self:TakePrimaryAmmo(self.Primary.TakeAmmo)
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
self.Weapon:SetNextSecondaryFire( CurTime() + self.Primary.Delay )
end
end[/lua]
:barf:
[editline]02:18PM[/editline]
This is what happens when you try to edit a SWEP generated from a SWEP Creator.
I know, I'm sorry about the appearance - I'm afraid I'm more familiar even with lua than I am with internet text. I tried to put it in the tags, but it really wasn't cooperating, so I decided to deal with the actual problem first and the user malfunction second.
Is that better?
[editline]09:29AM[/editline]
Also, quite the contrary - I have had plenty of success making my own SWEPs with the creator; I use it as a jumping-off point, and to set up a workable structure. What you see above is extremely heavily modified.
[editline]09:33AM[/editline]
So, philosophical and grammatical woes aside, how do I fix my gun?
There is an awful lot wrong with that code, so much in fact that I don't think that I have the motivation to fix it for you. However, I will say that you have ends where there shouldn't be ends and no ends where there should be ends.
Also, It isn't such a great idea to use code generated by a SWEP Creator as a base for your modifications, if you are using MakeR's SWEP Creator (which I think you are), then the output code is incredibly messy and somewhat random, making it difficult to read and (therefore) modify.
You are correct in surmising that I am using this particular SWEP creator, and it is new information to me that it is so messy - although, being somewhat inexperienced, I am still in that stage where it all looks rather the same to me.
I am relatively confident that if I had a clue as to where my ends ought to go I could puzzle it out from there. As I said, all I am getting from the game is that there should be one near 'else'. This doesn't tell me a whole lot.
MakeR's SWEP Creator produces incredibly messy code (I should know, I made it :smile:).
I will have a go at sorting your code out shortly.
Thanks very much - I appreciate it.
Here, taken from my incendiary weapon for a gamemode I'm working on. Change as you see fit.
The "AIShootBullet" function is called in the SWEP:PrimaryFire() of the swep_base.
[lua]local function IgnitionCallback(bouncenum, attacker, tr, dmginfo)
local ed = EffectData()
ed:SetOrigin(tr.HitPos)
ed:SetNormal(tr.HitNormal)
if tr.HitEntity then
ed:SetEntity(tr.Entity)
end
util.Effect("fireshot",ed)
if tr.Entity then
if tr.Entity:IsPlayer() and tr.Entity:Team() == TEAM_ALIEN then
tr.Entity:Ignite(math.random(1,5),0)
end
if tr.Entity:IsNPC() then
tr.Entity:Ignite(math.random(1,5),0)
end
end
end
function SWEP:AIShootBullet(dmg, numbul, cone)
local bullet = {}
bullet.Num = numbul
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector(cone, cone, 0)
bullet.Tracer = 1
bullet.Force = dmg * 0.5
bullet.Damage = dmg
if math.random(1,6)==1 then
bullet.Callback = function(a, b, c) IgnitionCallback(0, a, b, c) end
end
self.Owner:FireBullets(bullet)
self:SendWeaponAnim(ACT_VM_PRIMARYATTACK)
self.Owner:MuzzleFlash()
self.Owner:SetAnimation(PLAYER_ATTACK1)
end[/lua]
There you go, no need for me to go through it. :smile:
Again, this is all greatly appreciated, but you are overestimating my knowledge of lua code. Everything I've learned has been by fiddling with things - trial and error. I have little to no understanding of the overall structure of it. I am sure the above segment of code would be really very helpful; I just have no idea where to put it.
I thank you all; your tremendous patience is not lost on me.
[editline]11:59AM[/editline]
[QUOTE=NullPoint;19427231]There you go, no need for me to go through it. :smile:[/QUOTE]
Frankly, I still prefer your help. To make a metaphor of the whole thing, I'm a guy who just knows maybe what a couple of the trees look like, and I need help from someone who knows his way around the forest. If this is left in my hands I will end up standing there wondering what to do with it.
[lua]
local function IgnitionCallback(bouncenum, attacker, tr, dmginfo) // This function gets called when the bullet hits.
local ed = EffectData() // Creating an effect.
ed:SetOrigin(tr.HitPos) // Setting where the effect originates
ed:SetNormal(tr.HitNormal) // Setting the effect's normal
if tr.HitEntity then
ed:SetEntity(tr.Entity)
end
util.Effect("fireshot",ed) // Creating an effect with the effect data.
if tr.Entity then // If the bullet hit an entity
if tr.Entity:IsPlayer() or tr.Entity:IsNPC() then // If the entity is a player or an NPC
tr.Entity:Ignite(math.random(1,5),0) // Ignite the player/NPC
end
end
end
function SWEP:AIShootBullet(dmg, numbul, cone)
local bullet = {} // Creating the bullet table.
bullet.Num = numbul // Setting the amount of bullets fired.
bullet.Src = self.Owner:GetShootPos() // Telling the bullet where it comes from
bullet.Dir = self.Owner:GetAimVector() // Telling the bullet where it is headed,
bullet.Spread = Vector(cone, cone, 0) // Setting the spread
bullet.Tracer = 1
bullet.Force = dmg * 0.5 // Setting the force of the bullet impact
bullet.Damage = dmg // Setting the bullet damage.
if math.random(1,6) == 1 then // If the random value is 1 then
bullet.Callback = function(a, b, c) IgnitionCallback(0, a, b, c) end // Set the callback of the bullet to the above function so the function gets called when the bulet hits
end
self.Owner:FireBullets(bullet) // Shoot the bullet.
self:SendWeaponAnim(ACT_VM_PRIMARYATTACK) // Show the shooting animation.
self.Owner:MuzzleFlash() // Show the muzleflash
self.Owner:SetAnimation(PLAYER_ATTACK1) // Show the third person animation.
end[/lua]
Read the comments i placed.
[lua]local function IgnitionCallback(att, tr, dmginfo)
if ValidEntity(tr.Entity) then
tr.Entity:Ignite(math.random(5,10),0)
end
end
function SWEP:PrimaryAttack()
local bullet = {}
bullet.Num = self.Primary.NumberofShots
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector(self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
bullet.Tracer = 1
bullet.Force = self.Primary.Force
bullet.Damage = self.Primary.Damage
bullet.AmmoType = self.Primary.Ammo
if math.random(100) <= 15 then
bullet.Callback = IgnitionCallback
end
self.Owner:FireBullets(bullet)
self:ShootEffects()
self.Weapon:EmitSound(Sound(self.Primary.Sound))
self.Owner:ViewPunch(Angle(rnda,rndb,rnda))
self:TakePrimaryAmmo(self.Primary.TakeAmmo)
self.Weapon:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
end[/lua]
Add this to your weapon code, replacing (or merging with) your primary attack function. If it doesn't work or you need any more help, feel free to ask me in a PM.
What if the weapon shoots more than one shot, like a shotgun? Don't callbacks not work when there is more then one bullet?
[QUOTE=CowThing;19431711]What if the weapon shoots more than one shot, like a shotgun? Don't callbacks not work when there is more then one bullet?[/QUOTE]
No it works. It only doesn't work as expected when a gun shoots more than one bullet (like a shotgun) and you fire bullets in the callback. If you do this all other callbacks for the bullets from that shot won't get called.
You could of course do...
[code]function FireBullets(ent, attacker, inflictor, amount, dmginfo)
local FireMath = math.random(0,100)
if ent:IsNPC() and attacker:IsPlayer() then
if FireMath <= 15 then
ent:Ignite(10)
end
end
end
hook.Add("EntityTakeDamage", "Gasoline4Ever", FireBullets)[/code]
You could also add a table of weapons for this to act upon or just a Var to check... Kinda like.
[code]function FireBullets(ent, attacker, inflictor, amount, dmginfo)
local FireMath = math.random(0,100)
if ent:IsNPC() and attacker:IsPlayer() and attacker:GetActiveWeapon().HasFireBullets then
if FireMath <= 15 then
ent:Ignite(10)
end
end
end
hook.Add("EntityTakeDamage", "Gasoline4Ever", FireBullets)[/code]
But im sorry, im usually used to making coop gamemodes so.. I guess you would want this..
[code]function FireBullets(ent, attacker, inflictor, amount, dmginfo)
local FireMath = math.random(0,100)
if ent:IsValid() and attacker:IsPlayer() and attacker:GetActiveWeapon().HasFireBullets then
if FireMath <= 15 then
ent:Ignite(10)
end
end
end
hook.Add("EntityTakeDamage", "Gasoline4Ever", FireBullets)[/code]
[QUOTE=NullPoint;19431522][lua]local function IgnitionCallback(att, tr, dmginfo)
if ValidEntity(tr.Entity) then
tr.Entity:Ignite(math.random(5,10),0)
end
end
function SWEP:PrimaryAttack()
local bullet = {}
bullet.Num = self.Primary.NumberofShots
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector(self.Primary.Spread * 0.1 , self.Primary.Spread * 0.1, 0)
bullet.Tracer = 1
bullet.Force = self.Primary.Force
bullet.Damage = self.Primary.Damage
bullet.AmmoType = self.Primary.Ammo
if math.random(100) <= 15 then
bullet.Callback = IgnitionCallback
end
self.Owner:FireBullets(bullet)
self:ShootEffects()
self.Weapon:EmitSound(Sound(self.Primary.Sound))
self.Owner:ViewPunch(Angle(rnda,rndb,rnda))
self:TakePrimaryAmmo(self.Primary.TakeAmmo)
self.Weapon:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
end[/lua]
Add this to your weapon code, replacing (or merging with) your primary attack function. If it doesn't work or you need any more help, feel free to ask me in a PM.[/QUOTE]
Excellent! It works beautifully, excepting the minor error where the necessity to reload is overridden and the gun simply draws from the main ammo pool.
Still, I'm quite pleased with it.
[editline]04:12PM[/editline]
[QUOTE=Wizey!;19433030]You could of course do...
[code]function FireBullets(ent, attacker, inflictor, amount, dmginfo)
local FireMath = math.random(0,100)
if ent:IsNPC() and attacker:IsPlayer() then
if FireMath <= 15 then
ent:Ignite(10)
end
end
end
hook.Add("EntityTakeDamage", "Gasoline4Ever", FireBullets)[/code]
You could also add a table of weapons for this to act upon or just a Var to check... Kinda like.
[code]function FireBullets(ent, attacker, inflictor, amount, dmginfo)
local FireMath = math.random(0,100)
if ent:IsNPC() and attacker:IsPlayer() and attacker:GetActiveWeapon().HasFireBullets then
if FireMath <= 15 then
ent:Ignite(10)
end
end
end
hook.Add("EntityTakeDamage", "Gasoline4Ever", FireBullets)[/code]
But im sorry, im usually used to making coop gamemodes so.. I guess you would want this..
[code]function FireBullets(ent, attacker, inflictor, amount, dmginfo)
local FireMath = math.random(0,100)
if ent:IsValid() and attacker:IsPlayer() and attacker:GetActiveWeapon().HasFireBullets then
if FireMath <= 15 then
ent:Ignite(10)
end
end
end
hook.Add("EntityTakeDamage", "Gasoline4Ever", FireBullets)[/code][/QUOTE]
If this one would - in theory - work with a shotgun-style weapon, I may be using this too. I'm putting together a pack of these weapons.
Don't make a pack of weapons when you can barely code Lua.
[editline]11:30PM[/editline]
Not trying to be a dick or anything, but if its poorly made or something you're going to get a load of PM's/emails ranting about it being bad.
Correction: Don't make a pack of weapons when you can barely code Lua AND are prepared to settle for something less finished than what you have in mind.
Since I'm not prepared to settle, I don't think there will be a problem. Believe me, nothing irks me more than poor-quality downloads and I'm not about to add to the problem.
Okay, just trying to add a mini-filter to the Gmod crap pipe :P
Sorry, you need to Log In to post a reply to this thread.