• Help with this code please:
    33 replies, posted
Hey guys, So I have this code here: (From the C4 TTT File) [lua] function ENT:SphereDamage(dmgowner, center, radius) -- It seems intuitive to use FindInSphere here, but that will find all ents -- in the radius, whereas there exist only ~16 players. Hence it is more -- efficient to cycle through all those players and do a Lua-side distance -- check. local r = radius ^ 2 -- square so we can compare with dotproduct directly -- pre-declare to avoid realloc local d = 0.0 local diff = nil local dmg = 0 for _, ent in pairs(player.GetAll()) do if ValidEntity(ent) and ent:Team() == TEAM_TERROR then -- dot of the difference with itself is distance squared diff = center - ent:GetPos() d = diff:DotProduct(diff) if d < r then -- deadly up to a certain range, then a quick falloff within 100 units d = math.max(0, math.sqrt(d) - 490) dmg = -0.01 * (d^2) + 125 local dmginfo = DamageInfo() dmginfo:SetDamage(dmg) dmginfo:SetAttacker(dmgowner) dmginfo:SetInflictor(self.Entity) dmginfo:SetDamageType(DMG_BLAST) dmginfo:SetDamageForce(center - ent:GetPos()) dmginfo:SetDamagePosition(ent:GetPos()) ent:TakeDamageInfo(dmginfo) end end end end [/lua] And this one (C4 too only the explotion ent) [lua]local c4boom = Sound("c4.explode") function ENT:Explode(tr) if SERVER then self:SetNoDraw(true) self:SetSolid(SOLID_NONE) -- pull out of the surface if tr.Fraction != 1.0 then self:SetPos(tr.HitPos + tr.HitNormal * 0.6) end local pos = self:GetPos() if util.PointContents(pos) == CONTENTS_WATER or GetRoundState() != ROUND_ACTIVE then self:Remove() self:SetExplodeTime(0) return end local dmgowner = self:GetThrower() dmgowner = IsValid(dmgowner) and dmgowner or self.Entity local r_inner = 750 local r_outer = self:GetRadius() if self.DisarmCausedExplosion then r_inner = r_inner / 2.5 r_outer = r_outer / 2.5 end -- damage through walls self:SphereDamage(dmgowner, pos, r_inner) -- explosion damage util.BlastDamage(self, dmgowner, pos, r_outer, self:GetDmg()) local effect = EffectData() effect:SetStart(pos) effect:SetOrigin(pos) -- these don't have much effect with the default Explosion effect:SetScale(r_outer) effect:SetRadius(r_outer) effect:SetMagnitude(self:GetDmg()) if tr.Fraction != 1.0 then effect:SetNormal(tr.HitNormal) end effect:SetOrigin(pos) util.Effect("Explosion", effect, true, true) util.Effect("HelicopterMegaBomb", effect, true, true) timer.Simple(0.1, function() WorldSound(c4boom, pos, 100, 100) end) -- extra push local phexp = ents.Create("env_physexplosion") phexp:SetPos(pos) phexp:SetKeyValue("magnitude", self:GetDmg()) phexp:SetKeyValue("radius", r_outer) phexp:SetKeyValue("spawnflags", "19") phexp:Spawn() phexp:Fire("Explode", "", 0) -- few fire bits to ignite things timer.Simple(0.2, function(p) StartFires(pos, tr, 4, 5, true, p) end, dmgowner) self:SetExplodeTime(0) SCORE:HandleC4Explosion(dmgowner, self:GetArmTime(), CurTime()) self:Remove() else local spos = self:GetPos() local trs = util.TraceLine({start=spos + Vector(0,0,64), endpos=spos + Vector(0,0,-128), filter=self}) util.Decal("Scorch", trs.HitPos + trs.HitNormal, trs.HitPos - trs.HitNormal) self:SetExplodeTime(0) end end [/lua] And my Landmine code here: [lua] function ENT:Explode() local splode = ents.Create("env_physexplosion") //Push! splode:SetPos( self.Entity:GetPos() ) splode:SetKeyValue("magnitude", "230") splode:SetKeyValue("spawnflags", 2 + 16) splode:Spawn() local asplode = ents.Create("env_ar2explosion") //Boom cloud! asplode:SetPos( self.Entity:GetPos() ) asplode:Spawn() local BOOM = ents.Create("env_explosion") //Boom! BOOM:SetPos( self.Entity:GetPos() ) BOOM:SetKeyValue("iMagnitude", "230") BOOM:Spawn() splode:Fire("Explode",0,0) //Boom 1! asplode:Fire("Explode",0,0) //Boom 2! BOOM:Fire("Explode",0,0) //Boom 3! //Real damage! (no effects though) util.BlastDamage(self.Entity,self.Entity,self.Entity:GetPos(),66,1500) self.Entity:Remove() end [/lua] The question is, How would I make my landmine that it hurts though walls too, how would I transfer/ modding the code with the C4 code? All tho I want still the same radious "util.BlastDamage(self.Entity,self.Entity,self.Entity:GetPos(),66,1500)" Thank you so much for reading this. this is quite important for me. Thanks.
Simply replace your call to util.BlastDamage with the first function you posted called ENT.SphereDamage. I'm guessing you want a different damage setup so just mod the function near line 24 like so [lua] function ENT:SphereDamage(dmgowner, center, dmg, radius) local r = radius ^ 2 -- square so we can compare with dotproduct directly -- pre-declare to avoid realloc local d = 0.0 local diff = nil for _, ent in pairs(player.GetAll()) do if ValidEntity(ent) and ent:Team() == TEAM_TERROR then -- dot of the difference with itself is distance squared diff = center - ent:GetPos() d = diff:DotProduct(diff) if d < r then d = -1.5*((diff:Length()/radius)^2)+1.5; local dmginfo = DamageInfo() dmginfo:SetDamage(dmg*(d > 1 and 1 or d)); dmginfo:SetAttacker(dmgowner) dmginfo:SetInflictor(self.Entity) dmginfo:SetDamageType(DMG_BLAST) dmginfo:SetDamageForce(center - ent:GetPos()) dmginfo:SetDamagePosition(ent:GetPos()) ent:TakeDamageInfo(dmginfo) end end end end [/lua] You'll see I substitued kingsomething's crazy math with my own (damage is 100% until 50% of the explosion radius afterwhich it drops quadratically) [lua] self:SphereDamage(self.Entity, self.Entity:GetPos(), 66, 1500) [/lua]
[QUOTE=Slight;29620796]Simply replace your call to util.BlastDamage with the first function you posted called ENT.SphereDamage. I'm guessing you want a different damage setup so just mod the function near line 24 like so [lua] function ENT:SphereDamage(dmgowner, center, dmg, radius) local r = radius ^ 2 -- square so we can compare with dotproduct directly -- pre-declare to avoid realloc local d = 0.0 local diff = nil for _, ent in pairs(player.GetAll()) do if ValidEntity(ent) and ent:Team() == TEAM_TERROR then -- dot of the difference with itself is distance squared diff = center - ent:GetPos() d = diff:DotProduct(diff) if d < r then d = -1.5*((diff:Length()/radius)^2)+1.5; local dmginfo = DamageInfo() dmginfo:SetDamage(dmg*(d > 1 and 1 or d)); dmginfo:SetAttacker(dmgowner) dmginfo:SetInflictor(self.Entity) dmginfo:SetDamageType(DMG_BLAST) dmginfo:SetDamageForce(center - ent:GetPos()) dmginfo:SetDamagePosition(ent:GetPos()) ent:TakeDamageInfo(dmginfo) end end end end [/lua] You'll see I substitued kingsomething's crazy math with my own (damage is 100% until 50% of the explosion radius afterwhich it drops quadratically) [lua] self:SphereDamage(self.Entity, self.Entity:GetPos(), 66, 1500) [/lua][/QUOTE] Wait, I dont really get this, Im ment to add the ENT:SphereDamage from the C4 code to my landmine code, right? And then the edited line would be "util.BlastDamage(self.Entity,self.Entity:SphereDamage(),self.Entity,self.Entity:GetPos(),66,1500)" Not really sure tho. Also how would I need to edit my ENT:Explode() at my landmine code? Or is that not nessasary?
[QUOTE=Weapon317;29622236]Wait, I dont really get this, Im ment to add the ENT:SphereDamage from the C4 code to my landmine code, right? And then the edited line would be "util.BlastDamage(self.Entity,self.Entity:SphereDamage(),self.Entity,self.Entity:GetPos(),66,1500)" Not really sure tho. Also how would I need to edit my ENT:Explode() at my landmine code? Or is that not nessasary?[/QUOTE] Place the ENT:SphereDamage inside your entity's file somewhere. Replace line 22 of your Explode function with [lua] self:SphereDamage(self.Entity, self.Entity:GetPos(), 66, 1500) [/lua]
[QUOTE=Slight;29625594]Place the ENT:SphereDamage inside your entity's file somewhere. Replace line 22 of your Explode function with [lua] self:SphereDamage(self.Entity, self.Entity:GetPos(), 66, 1500) [/lua][/QUOTE] Ok did this, doesnt work though, It explodes but it doesnt hurt though walls, any ideas how to fix this?
Help?
Bump
Why don't you loop ents.FindInSphere and check if it is a player, then just give them damage?
Because in the original C4 script he dint used that either, So I think there must be some way to fix this, And to be honest, Not really sure how to make the ents.FindInSphere thing
forget it this section of the forum is died already... no one cares to help a newbie out like me i posted thread NO ONE REPLY =/
[QUOTE=iTeehee;29671267]forget it this section of the forum is died already... no one cares to help a newbie out like me i posted thread NO ONE REPLY =/[/QUOTE] If you actually have a reasonable IQ(determined from your post) and you have a basic understanding of lua and actually show you have tried to do it your self you will get useful reply's
[QUOTE=King Flawless;29671522]If you actually have a reasonable IQ(determined from your post) and you have a basic understanding of lua and actually show you have tried to do it your self you will get useful reply's[/QUOTE] Well I know how to make a loop, its just the "ents.FindInSphere" thing what I dont really understand
[QUOTE=Weapon317;29673583]Well I know how to make a loop, its just the "ents.FindInSphere" thing what I dont really understand[/QUOTE] ents.FindInSphere outputs a table of all the entity's inside the sphere
Hmm still not really sure how to make it, atleast how to start the loop then, I looked on the wiki and there was something like function arguments with vector pos and radious, but it needs to be the same radious as this "self:SphereDamage(self.Entity, self.Entity:GetPos(), 66, 1500)"
[QUOTE=Weapon317;29673583]Well I know how to make a loop,[/QUOTE] [QUOTE=Weapon317;29673779]Hmm still not really sure how to make it, atleast how to start the loop[/QUOTE]
Yeah I do know how to make a loop, but I always had it with (players.getall) not with entities
[QUOTE=Weapon317;29673954]Yeah I do know how to make a loop, but I always had it with (players.getall) not with entities[/QUOTE] Its exactly the same concept.... and players are entities
Well I never did that concept so im not really sure how to start, can you maybe give me a example how to begin? Also even if I had it correct I still dont know how to make the same radious as this: "self:SphereDamage(self.Entity, self.Entity:GetPos(), 66, 1500)"
[lua] for k, v in pairs(ents.FindInSphere(self:GetPos(), radius) do if IsValid(v) && v:GetClass() == "player" then --do stuff[/lua] ?
and then I have the original radious what I had already? "(self.Entity, self.Entity:GetPos(), 66, 1500)" ?
What the hell is wrong with reading the wiki example [lua]local orgin_ents = ents.FindInSphere(self:GetPos(),PUT A NUMBER HERE TO SAY HOW BIG THE RADIUS IS )[/lua]
[QUOTE=King Flawless;29677919]What the hell is wrong with reading the wiki example [lua]local orgin_ents = ents.FindInSphere(self:GetPos(),PUT A NUMBER HERE TO SAY HOW BIG THE RADIUS IS )[/lua][/QUOTE] Ah Thanks now I understand, Dont forget our humans are visual based, we need to see a good example before we can understand it good, thats my theory,, meh never mind. Thanks Ill work something out
Ok I edited it, Still doesnt work tho (Hurt though walls), This is the code: [lua] function ENT:FindInSphere() for k, v in pairs(ents.FindInSphere(self:GetPos(), 66)) do if IsValid(v) && v:GetClass() == "player" then if v:IsPlayer() && v:IsValid() && v:Alive() && !v:IsActiveTraitor() then self.Entity:Hop() end end end end [/lua]
Make trace from entity to player, if it hits worldspawn (walls and stuff) just abort hurting him, also if it hits prop, make new trace, until it hits player (abort only if it hits worldspawn).
Hmm I never made a trace, Not really sure how to start, could you maybe show me a example?
Bump, its still unresloved
You will need to use [b][url=http://wiki.garrysmod.com/?title=Util.TraceLine]Util.TraceLine [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]. You will pass it a table like in the example in the Wiki, I've pasted an expanded example below with comments. [lua] -- Variable names take from the wiki, tracedata could be anything, and so could trace -- Sometimes it helps to change the names, bombTraceData and losTrace are more descriptive local tracedata = {} -- Create an empty table to hold the tracedata tracedata.start = pos -- start is where in the world the trace will start tracedata.endpos = pos+(ang*80) -- endpos is where the trace will end tracedata.filter = self.Owner -- the filter is used to exclude entities from the trace local trace = util.TraceLine(tracedata) -- trace will contain the results of the trace -- above is the same as below, I just put in example values more like what you'll be using local bombTraceData = {} -- Create an empty table to hold the tracedata bombTraceData.start = bombEntity:GetPos() -- start is where in the world the trace will start bombTraceData.endpos = target:GetPos() -- endpos is where the trace will end bombTraceData.filter = bombEntity -- the filter is used to exclude entities from the trace local losTrace = util.TraceLine(bombTraceData) -- trace will contain the results of the trace [/lua] Traces stop when they hit something or reach the endpos A [url=http://wiki.garrysmod.com/?title=Traceres]traceres[/url] table will be returned. Most of the time you only need a few of the values from it depending on what you are doing, as described in posts above you'd be checking for trace.HitWorld which is true if you hit the world. The other thing you would need to check if it didn't hit the world, trace.Fraction will return < 1 if it stopped before the endpos at which point you check and see what you hit. You could also check trace.HitNonWorld like in the wiki example. You can get the entity it hit using trace.Entity and start a new trace with the same structure just changing the start, endpos and filter until you either do hit the world, the max distance(endpos) or trace.Entity is your target entity. This is just a basic overview, you can get as simple or as complex as you want. What I would do about non world stuff in the way is check the mass of the object and if it's heavy enough it can stop the blast too. Hope this helps.
[QUOTE=Fantym420;29763370]You will need to use [b][url=http://wiki.garrysmod.com/?title=Util.TraceLine]Util.TraceLine [img_thumb]http://wiki.garrysmod.com/favicon.ico[/img_thumb][/url][/b]. You will pass it a table like in the example in the Wiki, I've pasted an expanded example below with comments. [lua] -- Variable names take from the wiki, tracedata could be anything, and so could trace -- Sometimes it helps to change the names, bombTraceData and losTrace are more descriptive local tracedata = {} -- Create an empty table to hold the tracedata tracedata.start = pos -- start is where in the world the trace will start tracedata.endpos = pos+(ang*80) -- endpos is where the trace will end tracedata.filter = self.Owner -- the filter is used to exclude entities from the trace local trace = util.TraceLine(tracedata) -- trace will contain the results of the trace -- above is the same as below, I just put in example values more like what you'll be using local bombTraceData = {} -- Create an empty table to hold the tracedata bombTraceData.start = bombEntity:GetPos() -- start is where in the world the trace will start bombTraceData.endpos = target:GetPos() -- endpos is where the trace will end bombTraceData.filter = bombEntity -- the filter is used to exclude entities from the trace local losTrace = util.TraceLine(bombTraceData) -- trace will contain the results of the trace [/lua] Traces stop when they hit something or reach the endpos A [url=http://wiki.garrysmod.com/?title=Traceres]traceres[/url] table will be returned. Most of the time you only need a few of the values from it depending on what you are doing, as described in posts above you'd be checking for trace.HitWorld which is true if you hit the world. The other thing you would need to check if it didn't hit the world, trace.Fraction will return < 1 if it stopped before the endpos at which point you check and see what you hit. You could also check trace.HitNonWorld like in the wiki example. You can get the entity it hit using trace.Entity and start a new trace with the same structure just changing the start, endpos and filter until you either do hit the world, the max distance(endpos) or trace.Entity is your target entity. This is just a basic overview, you can get as simple or as complex as you want. What I would do about non world stuff in the way is check the mass of the object and if it's heavy enough it can stop the blast too. Hope this helps.[/QUOTE] Hmm I get the point and really great that you made it up like this, but still Im not really sure what to do.. :l All tho this is a good tutorial
Basically the problem is that that code uses util.BlastDamage. Walls and stuff will block some of the blast damage, which you don't want here. TTT gets around this by just going through all the players and dealing damage based on how far away that player is. To loop through a table: [lua] local tab = { 3, "cheese", "some bacon", 5.67, ["lie"] = "cake" } -- You can rename key or value to whatever you want, key is the index of the value in the table -- If you can't understand this bit, you need to (re)learn lua for key, value in pairs( tab ) do print( key, value ) end Output: 1 3 2 cheese 3 some bacon 4 5.67 lie cake [/lua] player.GetAll() [lua] local players = player.GetAll() print(type( players )) Output: table -- I wonder how I could loop through all the players...? [/lua] :eng101: For every player you'll want to deal damage based on the distance from the explosion. Distance is Vector:Distance( Vector ) Damage can be done with [b][url=http://wiki.garrysmod.com/?title=Entity.TakeDamage]Entity.TakeDamage [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] [b]Please learn from my code instead of just copying it. Especially the code you copied directly from my landmine-hopper things, it's three years old and I was rubbish at Lua then.[/b]
When the entity explodes, do a find in sphere to get any entities in the blast radius. Then loop through the entities you got from the find and do a trace from the bomb to each entity that is a player. If the trace hit the player then nothing is blocking, so they die. Now, the rest depends on how you want it to work, if you want any object to stop the blast then if the trace.Entity is not the player you are tracing at then no damage, if you want only the world to stop the blast then if trace.Entity is not the player or the world, start a new trace from where you hit using what you hit as the filter, and the player is the endpos again. Repeat until either you hit the world or the player. Pseudo code -- Will not work as is, this is just an outline/example [lua] function bombExplode(bombPos, bombRadius) sphereEnts = ents.FindInSphere(bombLocation, bombRadius) -- Grab ents near bomb local hitPlayer = false -- Setup variable to check if we hit player for _, ent in pairs(sphereEnts) do -- loop the ents if ent:IsPlayer() then -- Check if it's a player tracedata = {} -- setup first trace tracedata.start = bombPos tracedata.endpos = ent:GetPos() tracedata.filter = ent trace = trace(tracedata) if trace.Entity == ent then -- see if the trace ended with the player hitPlayer = true -- then set it so we damage the player end if !(trace.Entity == ent) and !(trace.Entity:IsWorld()) then -- if we didn't hit the player or the world then... doAnotherTrace = {} -- setup another trace doAnotherTrace.start = trace.HitPos doAnotherTrace.endpos = ent:GetPos() doAnotherTrace.filter = trace.Entity newTrace = trace(doAnotherTrace) if newTrace.Entity == ent then -- did we hit the player? hitPlayer = true -- then set it so we damage the player end end if hitPlayer then -- if we hit the player ent:Kill() -- kill the player end end hitPlayer = false -- reset variable for next player end end [/lua] This could also be done with a recursive function, or masks, but it's best to start simple. Basically the way the code above would run if I wrote it as real code is, if the player is in the blast radius and there is only one prop or entity between him and the bomb, the player dies, if there's more than 1 prop/ent in the way or the world, the player won't die. if you want it to go till it hit world no mater how many props are in the way, you'll need a recursive function(a function that calls it self until a condition is met). If you still can't get it put it in the requests and i'll make a real function for it either later today or tomorrow.
Sorry, you need to Log In to post a reply to this thread.