Assignment to world in LightningDamage

Discuss programming in the QuakeC language.
Post Reply
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Assignment to world in LightningDamage

Post by Cobalt »

Trying to understand how the trace_ent is takedamage and also world at the same time here.

^7assignment to world.velocity_z (field 18) in server
^7s25542: ^5IFNOT GLOBAL20835, statement 25550
^7s25543: ^6FIELD_S other (=entity 2), classname (=.classname), GLOBAL20836
^7s25544: ^2EQ_S GLOBAL20836, IMMEDIATE (=player), GLOBAL20837
^7s25545: ^5IFNOT GLOBAL20837, statement 25550
^7s25546: ^1ADDRESS trace_ent (=entity 0), velocity_z (=.velocity_z), GLOBAL20838
^7s25547: ^6FIELD_F trace_ent (=entity 0), velocity_z (=.velocity_z), GLOBAL20839
^7s25548: ADD_F GLOBAL20839, IMMEDIATE (=400), GLOBAL20840
^7s25549: ^1STOREP_F GLOBAL20840, GLOBAL20838
^7 weapons.qc : LightningDamage : statement 49
^7 weapons.qc : W_FireLightning : statement 46
^7 player.qc : player_light1 : statement 20
^7 weapons.qc : W_Attack : statement 93
^7 weapons.qc : W_WeaponFrame : statement 8
^7 client.qc : PlayerPostThink : statement 32

Code: Select all

if (trace_ent.takedamage)
	{
		particle (trace_endpos, '0 0 100', 225, (damage * 4));
		T_Damage (trace_ent, from, from, damage);
		if (self.classname == "player")
		{
			if (other.classname == "player")
			trace_ent.velocity_z = (trace_ent.velocity_z + 400);
			
		}
	}
Im suspecting "other" should be trace_ent, but turns out as Im electrocuting an enemy Im pushing it up to the ceiling as I keep the beam on him - never saw it do this before.
Dr. Shadowborg
InsideQC Staff
Posts: 1120
Joined: Sat Oct 16, 2004 3:34 pm

Re: Assignment to world in LightningDamage

Post by Dr. Shadowborg »

Code: Select all

         if (other.classname == "player")
         trace_ent.velocity_z = (trace_ent.velocity_z + 400);
The other should indeed be trace_ent. I should point out that this will only make the push work on targets that happen to be a player, and you may want to change the velocity_z to match the lightning vector, otherwise it will look strange. (i.e. players will be shooting straight up into the air + however much the damage push within T_Damage decides upon, as opposed to being pushed along the aim direction.)


...and now I see that this is in stock vanilla quake code. And also is kinda nasty to look at. And is also buggy because of the other being used instead of trace_ent. :shock:

I'm guessing that its SUPPOSED to allow the lightning to penetrate three targets sorta like a railgun, but no way in hell is it going to do that as it is.

/me sighs

I REALLY need to get back to working on quake projects one of these days...but I need to find time first...argh... :cry:
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: Assignment to world in LightningDamage

Post by frag.machine »

if the traceline () didn't hit any valid entity (for example, if the lightning gun beam don't touch anything that can be hurt, like monsters, other players, doors), it returns a "null" entity reference (0), which points to the world. And by definition you shouldn't try to mess with the world entity attributes.
That's why you ought to always check if any entity returned by traceline() (or any function actually) is valid simply testing it:

Code: Select all

if (trace_ent != world) {
// do stuff here
}
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Cobalt
Posts: 445
Joined: Wed Jun 10, 2009 2:58 am
Location: New England, USA
Contact:

Re: Assignment to world in LightningDamage

Post by Cobalt »

True, however world.takedamage is 0, or is it actually a null field? Either way I would expect the code not to get seen because world cant takedamage. I changed it to this, and seems to stop the error however the target client does still hit the ceiling as the velocity field seems to still be hit with that same code somehow. Maybe I will try reducing the upward z valuein case what I am seeing is just some residual effect , at any rate 400 is kinda high, and yea Dr Shadowborg is right this is vanilla QC that I guess no one ever picked up this bug in it before. I have played on servers where the beam pushed you back into walls etc, but I thought that was the default result of the orogonal beam code.

Code: Select all

if (trace_ent.takedamage)
	{
		particle (trace_endpos, '0 0 100', 225, (damage * 4));
		T_Damage (trace_ent, from, from, damage);
		if (self.flags & FL_CLIENT)
		{
			if (trace_ent.flags & FL_CLIENT)
			if (trace_ent.flags & FL_ONGROUND)
			trace_ent.velocity_z = (trace_ent.velocity_z + 400);
			
		}
	}
frag.machine wrote:if the traceline () didn't hit any valid entity (for example, if the lightning gun beam don't touch anything that can be hurt, like monsters, other players, doors), it returns a "null" entity reference (0), which points to the world. And by definition you shouldn't try to mess with the world entity attributes.
That's why you ought to always check if any entity returned by traceline() (or any function actually) is valid simply testing it:

Code: Select all

if (trace_ent != world) {
// do stuff here
}
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Assignment to world in LightningDamage

Post by Spike »

This bug is reasonably well known in quakeworld. If you're standing on the secret door on dm6 and shoot it with the LG then the door will go flying upwards (before its think function causes it to teleport to the spot its meant to be in).
Juggling players with the LG is an amusing idea, but really it just means that the LG become FAR too overpowered as it means the victim loses most of their ability to dodge, essentually becoming a sitting duck as they go flying.
Imho, the best thing to do is to just remove the velocity change entirely, along with its two if statements.

T_Damage provides its own knockback, but its not normally strong enough to completely counter gravity in part because the attacker would have to be below the victim, and the floor tends to get in the way.
Naturally this is more noticable if you have pent/god mode, as you'd normally die too quickly otherwise, but it is a standard feature.

Also, note that T_Damage can kill exploboxes that do T_RadiusDamage checks which involve tracelines, if the last traceline hits the world then trace_ent is world by the time T_Damage returns.
There may be other ways for T_Damage to change trace_ent.
This is just one reason why globals are evil.

world.takedamage can also potentially be set by ANY spawn function, and also potentially any function that is called within the first 0.2 seconds.
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: Assignment to world in LightningDamage

Post by frag.machine »

Cobalt wrote:True, however world.takedamage is 0, or is it actually a null field? Either way I would expect the code not to get seen because world cant takedamage.
If the entity reference is invalid, it's not reasonable to expect its attributes to be consistent. In other words, takedamage has no meaning to the world entity, so it can have any value.

Personally although I consider QuakeC a really clever feature in the Quake engine, the implicit association "entity 0=world=null" was a poor decision that leads to this kind of problem. Had the "null" were associated to some invalid value for entity index like -1 it would be easier to the interpreter or builtins to detect the wrong reference.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Assignment to world in LightningDamage

Post by r00k »

just skimmed this thread but cant you just cludge it with

Code: Select all

 
if (trace_ent != world)
at the top?

edit:
oops frag already said this....
Post Reply