Seeing how calling ent.FireBullets is the only way to really do bullets properly in gmod, is there anyway way to mask the bullet traces? Particularly I want the bullets to pass through some players. I really want to avoid making my own bullet firing function.
I’m afraid the best way to do this is just using callbacks.
What do you mean?
If you want a bullet to pass through a player, simply call another :FireBullets() inside of the callback for the first, and compensate for where the bullet should leave.
Why not just make a trace and use MASK_SHOT ?
He’s probably talking about forcing the bullets to interact differently, and GMod doesn’t allow you to change the masks. You’d have to be using bindings that allowed you to do that.
That’s more meant for melee weapons, but even that is a horrible way to write a melee weapon, and anyone who does it cleanly doesn’t use that.
[editline]10th January 2011[/editline]
http://www.garrysmod.org/downloads/?a=view&id=81766 You can recycle the old penetration code I used in this if you want.
Oh that’s what I thought you meant, I was planning to look into this I’m just hoping there are no serious drawbacks. Thanks.
Remember how I said I didn’t want to do that (make my own FireBullets function)? This is because I’d have to do my own clientside prediction with an offset table and everything and even then I feel the end result would yield some more unexpected problems.
In the past, I accidentally caused a C-stack overflow whilst writing some bullet penetration code. I think back then, what I did was override the FireBullets function, so I could get bullet penetration on C++ weapons in combination with a TakeDamage hook.
Just don’t do that. I’m sure there’s a proper way to do that with that hook, but it’s just a bad idea.
Things work really nice using bullet callbacks actually. Simply overriding FireBullets and calling FireBullets again in order to shoot through things yields perfect results basically.
Eveything is working now except for calls to FireBullets where more than one bullet is fired (aka shotguns). This is a hurdle I can’t seem to overcome. I’ve tried splitting calls to FireBullets using more than 1 bullet up into individual calls firing one bullet each (which overcomes the callback issue) however that causes the engine to use the same internal offset vector (from the list of random vectors stored clientside and serverside) which means 8 bullets all get fired down the same normal. I’m guessing all calls to fireBullets use the same internal vector until the next frame or until the server says to increment?
Any ideas on how to fix this issue. Its on the wiki too:
I have two work arounds, one which would require me doing as many as 1 + 2 + 3 + 4 + 5 + … + numbullets calls to FireBullets, the other would just have me use my own damage traces after the initial bullet callback is called which is what I’m going to use since the other is too expensive.
Been there, trust me, I couldn’t figure out a solution, so I didn’t bother. I can think of a solution right now, but considering the execution would be done in one frame, it probably wouldn’t work, additionally it’s so unbelievably hacky, it’s stupid.
Create x amount of entities you need in parallel with how many pellets you want shot, make these point entities and just spawn them at the vector origin. Now call :FireBullets() from each point entity, and assign the proper attacker, but make the shot start from the gun in question.
My theory is that since you can’t do multiple :FireBullets() in a loop in a single frame with a spread vector and actually get a spread from a single entity, that maybe you can generate a different spread based on a different entity. (Totally guesswork here.) Alternatively (and this could cause unwanted bugs), call :FireBullets() instantly on the next frame in x successions to create the illusion of a buckshot.
I have no idea what either one of these concepts will yield for you, but I’m just saying that I’ve tried to do exactly what you’re going on with, and I stopped because I didn’t feel like trying to think up new hacky ways to get around this.
The two solutions above may just work, however.
Your incremental numbullet calls wouldn’t work, as I said above, they use the same shot modifier, so they’ll all head in exactly the same direction, causing no spread.
All i could think of is maybe having an array of directions with the spread angle wished as a value for each pellet.Then using the array and re-shooting the bullets.You might want to have multiple groups of direction as to make it seem random each primary fire. Sorry if this doesn’t make sense but in my mind i can see how it works.
Yeah, but you wouldn’t be able to use Valve’s method of bullet spread, because you’d have to have a bunch of FireBullets going in straight lines with no spread, and rotating the direction each bullet is going in. Replacing the traditional spread would take some decent amount of math.
found this on the bullet wiki.
local degrees = 20 local spreadVal = math.sin(math.Deg2Rad(degrees*0.5)) local spread = Vector(spreadVal, spreadVal, spreadVal);
Am i reading the wiki wrong or is that the formula for bullet spread?
I will have to test this, but like you said it is sort of hacky creating entities then removing them in an instant. You’re assuming that if the entity is different, a different offset vector will be used which seems intuitive, however, I feel like the internal vector pointer is shared between entities and even clients meaning all clients are on the same page in terms of the offsets and they are just incremented as the game ticks. I can say for sure multiple calls to FireBullets on the same entity uses the same vector offset each time. I’m not sure about changing the spread. If there is really an internal list of vectors and not just a list of numbers I would assume the spread is just multiplied by the offset vector. However, if there were a number list then the engine could apply an algorithm using that number to x, y, and z components of the spread vector which could yield completely different firing normals for each weapon with a different spread. I will test this. Edit: It is an offset vector list. I made each call to FireBullets do 3 more calls with a spread adjusted by 0.1 each time and they were all in a straight line.
What I tested actually did work it was just too expensive. It essentially took a call to FireBullets with a greater bullet num than one and for looped it calling FireBullets(binfo) with binfo.Num = n (n being the increment variable) each time. It would then only do my “shoot through” callback if it was the nth bullet (aka the one with a new internal spread offset) so that the callback was only being called once per call to FireBullets. I was able to identify a bullet as the nth bullet, not by when it hit, but by using a simple lookup table with keys as the internal offset vector.
Its basically my horrible fallback option if nothing else works, but I feel this next solution with doing my own traces and effects will do fine.
The reason we have to use FireBullets and not do our own bullets is because the source engine maintains a magic list of offset vectors that are synchronized between the server and client which is only accessible via FireBullets. They sync a list for each entity so that we can fire bullets with pseudo-random spread while still predicting the bullets clientside. We can, however, use FireBullets and their hit callbacks to then do our own trace and effects since we now have the internal offset vector available to lua.
I wouldn’t really suggest garry make the internal offset list readable by lua because that would make nospread hacks very simple. I would, however, recommend he add masks to FireBullet calls or at the very least get around this callback issue.
By looking the the FireBulletsInfo struct, there wouldn’t actually be a binding he could write to extend the usage of FireBullets, however he could add a hook to the function which modifies what it hits.
Ah I didn’t take that into consideration, I thought he had full access to anything. Well I come with a better solution to the shotgun issue than I could have hoped for.
While I was making my own bullet effects I noticed I could not create “Impact” effects within any call stack originating from a FireBullets callback function. I realized this because doing a timer.Simple() allowed me to create the impact effects (via util.Effect) while calling util.Effect inside the callback always failed. I tried to apply this similar strategy to the FireBullets issue and lo and behold it worked. But I had to find something that allowed me to fire the bullets from a different function stack, like timer.Simple would, but during the same frame so no accuracy is lost.
The gamemode Think function is actually called after these FireBullet callbacks are processed (proved by setting a var in the FireBullet callbacks printing the framenumber via FrameNumber() and having Think print the FrameNumber it saw the variable and they were always the same). This means I can have a special callback for FireBullet calls with multiple bullets which, instead of calling FireBullets inside of a FireBullets callback’s function stack which was our problem, I can insert the bullet info into a table and have the Think hook interpet the table and do the normal singular FireBullets calls.
This seems to work fine so far (I lined 10 bots in a row up with no accuracy loss), I just have to do player:LagCompensation() during the think hook to ensure lag compensation is still in effect. The bullets are still processed on the same frame, just in different function stacks.
Actually player.LagCompensation is crashing me… any ideas? And whats with this IsFirstTimePredicted function? Does that have anything to do with lag comp? I read on the net that lag comp is preformed automatically when shooting players not on your team or when mp_friendlyfire is 1.
To be honest, I have absolutely no clue why it’s crashing you, but I can tell you weapon prediction in GMod is not typical prediction for some reason. I still can’t really pull off complex reloading that’s done in the Source SDK as a result. (Works only partially, some prediction issues are noticeable.)
[editline]11th January 2011[/editline]
Your method of executing the callbacks was brilliant, I gotta say, too.
Hmm odd. Well the good news is I don’t seem to need it as its not called in any of Garrys code or any TTT code. Good enough for me I suppose.
Thanks, unfortunately I face a new problem that I might just have to deal with involving getting players to move through props. I may make a thread about it too but I need to try some other things first.