Announcement

Collapse
No announcement yet.

dmtx powerup glow and wallhacks

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • dmtx powerup glow and wallhacks

    This story is a bit longer than it's worth, and if you're named here, you may feel picked on, but don't fret until the end. Anyway, read on for some cheat testing on a popular dm server.

    I don't remember when I first heard about the quad damage glow being important to DM players. That is, the ability to see a quad holder's glow around corners and through some thinner walls. This classic feature was was broken/disabled when anti-wallhack measures (called "cullentities") were implemented on many servers in 2011. The problem is a bit technical, but know that a "thing", like a player, can contain a glow. Yet cullentities hides players' "things" from each other. For example, for two players separated by a wall, each does not receive the other player "thing", and thus a wallhack cannot see a player behind the wall. But this also keeps the glow from appearing through walls like it used to.

    Today, however, the dmtx server is way ahead by having the powerup glow work through walls. It seems no one plays on any other dm server any more. What I heard was Tremor fixed the problem on his server so that players could see the glow without issue. Additionally, there was a post made on the runequake forums (Rune Central View topic) where Mindz tried to get Tremor to share his code with Slot Zero and Gdr (for their dm servers). There was no reply from Tremor there, and, eventually, I found that he didn't want to divulge his secret. I didn't (and still don't) know the guy, but his reaction seemed weird. In fact, I couldn't think of a way that it was possible to fix the glow issue without re-enabling wallhacks! Either Tremor was way smarter than me, or he was lying. But- how to tell? I needed a wallhack.

    I didn't want to download and run one, since I'd have to trust who-knows-what from whatever website. Pak2 was another option, but using it didn't guarantee answers if he had a smart solution. Basically, I was looking at having to make my own wallhack, and I didn't want to give it that much effort... until recently. And after near a whole day of wrestling with Visual Studio, learning some quake functions, etc, I was able to succeed.

    So I tested it on the dmtx server, and what I found is that cullentities is still enabled as expected, but when someone picks up a quad, you can then see them through the wall with a wallhack. You can see them whether or not the glow is visible from your point of view. This is a sort-of half solution which may be considered good enough, but it is not flawless.

    Anyway, I wasn't sure what to do, so I searched the forum for anything about dmtx and Tremor that would let me get a lead-in on calling him out. So I found a thread about dmtx, and I was a bit shocked to see what lay therein. It turns out that Tremor's code is actually R00k's: http://quakeone.com/forums/quake-tal...quaketx-9.html. AND Tremor thinks that allowing such a limited wallhack ability is worth seeing quad glow... What this means is: the code is in public, I could have just seen it in the first place, and Tremor hadn't fixed the problem in some super secret smart way... in fact, he never even claimed it was.

    (tl;dr) I wasted a day for nothing.

    A this point, I am still inspired to find a flawless solution, but that will be a part #2 of this story, currently in progress.

  • #2
    Additionally, there was a post made on the runequake forums (Rune Central View topic) where Mindz tried to get Tremor to share his code with Slot Zero and Gdr (for their dm servers). There was no reply from Tremor there, and, eventually, I found that he didn't want to divulge his secret. I didn't (and still don't) know the guy, but his reaction seemed weird. In fact, I couldn't think of a way that it was possible to fix the glow issue without re-enabling wallhacks! Either Tremor was way smarter than me, or he was lying. But- how to tell? I needed a wallhack.
    Here's the code i gave Tremor, actually this one might be more robust than the one he is running.

    Code:
    qboolean SV_InvisibleToClient(edict_t *viewer, edict_t *seen)
    {
    	int i;
    	trace_t	tr;
        vec3_t	start;
        vec3_t	end;
    	extern trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
    	extern qboolean CL_Clip_Test(vec3_t org);
    	int it;
    	int vi;
    	if (svs.maxclients == 1)//Ok so, singleplayer saved games crash with this enabled.
    		return false;
    
    	vi = (int)viewer->v.colormap - 1;
    
    	if (seen->visibletime[vi] > sv.time)//dont check this ent for this client every frame! Once per second is enough.
    		return false;
    
    	it = (int)(seen->v.items);
    
    	//R00k: DM players want to see the Quad/Pent glow. Dont cull them at the moment...(fixme?)
       	if ((strcmp(pr_strings + seen->v.classname, "player") == 0) && ((it & IT_QUAD) || (it & IT_INVULNERABILITY)))
    	{
    		return false;
    	}	
    
    	if (sv_cullentities.value == 1)    //1 only check player models, 2 = check all ents
    	{
    		if (strcmp(pr_strings + seen->v.classname, "player"))
    			return false;
    	}
    
    	if (seen->v.movetype == MOVETYPE_PUSH )
        {
    		if (sv_cullentities.value == 3)    
    		{
    	 		if (CL_Clip_Test(seen->v.origin)== false)
    				return false;
    		}
    		else
    			return false;
        }
    
        memset (&tr, 0, sizeof(tr));     
        tr.fraction = 1;
    
        start[0] = viewer->v.origin[0];
        start[1] = viewer->v.origin[1];
        start[2] = viewer->v.origin[2] + viewer->v.view_ofs[2];
    
        //aim straight at the center of "seen" from our eyes
        end[0] = 0.5 * (seen->v.mins[0] + seen->v.maxs[0]);
        end[1] = 0.5 * (seen->v.mins[1] + seen->v.maxs[1]);
        end[2] = 0.5 * (seen->v.mins[2] + seen->v.maxs[2]);            
    
        tr = SV_ClipMoveToEntity (sv.edicts, start, vec3_origin, vec3_origin, end);
    
    	if (tr.fraction == 1)// line hit the ent
    	{	
    		seen->visibletime[vi] = sv.time + 1;//cvar this value?
            return false;
    	}
    
        memset (&tr, 0, sizeof(tr));                
        tr.fraction = 1;
    
    	//last attempt to eliminate any flaws...
        if ((!strcmp(pr_strings + seen->v.classname, "player")) || (sv_cullentities.value > 1))
        {
            for (i = 0; i < 64; i++)//change 64 to something lower FIXME cvar?
            {
                end[0] = seen->v.origin[0] + offsetrandom(seen->v.mins[0], seen->v.maxs[0]);
                end[1] = seen->v.origin[1] + offsetrandom(seen->v.mins[1], seen->v.maxs[1]);
                end[2] = seen->v.origin[2] + offsetrandom(seen->v.mins[2], seen->v.maxs[2]);
    
                tr = SV_ClipMoveToEntity (sv.edicts, start, vec3_origin, vec3_origin, end);
      
    			if (tr.fraction == 1)// line hit the ent
    			{
    			    //Con_DPrintf (1,va("found ent in %i hits\n", i));
    				seen->visibletime[vi] = sv.time + 1;//cvar this value?
    				return false;
    			}
            }
        }
        return true;
    }
    U have to make a couple global variables, and call this function in sv_main.c

    I wanted to just, have it so that if they had the glow EF_DIMLIGHT then send the player's model as null, but the engine has it where if the player doesnt have a model then it's culled.
    Code:
    	// ignore ents without visible models
    			if (!ent->v.modelindex || !pr_strings[ent->v.model])
    				continue;
    It should be an easy work-around, though, they were happy enough with this patch that i didnt really pursue it any further.

    You could add a client field ".culledQuad" then set that true if a> they have quad and b> they were culled and bypass this check ; else reset to False.

    let me know if you have troubles implementing it.
    Last edited by R00k; 06-29-2015, 10:49 AM.
    www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

    Comment


    • #3
      Thanks for sharing that code. The 64 line test is interesting, since I had wondered about the version I had, where the code only checks the player's center and corner points for visibility. In this case, there should be a weird case where a player's center and corners were all obstructed, but some midsection should be visible. Thus, the code will hide a player incorrectly in this case. Also, I'm glad that the 64 lines aren't done between every player for every frame of the game!

      I had not known about SV_ClipMoveToEntity(), and I'm thinking it's a test for an entity when moving a certain direction/distance against the solid world? Like a fat version of a traceline?

      However, this code shares the mostly good-enough solution to quad glow through walls, as noted.

      Editing the client to glow for null model quake players with quad is actually the easiest solution to code, but getting people to update their Quake client engine code, and asking players to download them seems like a big hurdle. Especially if dmtx keeps its good-enough fix. I did test this, too, in my hunt for a perfect solution, and I found that Darkplaces actually already does this kind of glow. However, its glow is very weird to me, since it doesn't light up the walls.

      Comment


      • #4
        LH adopted the theory of cullentites from TRIBES. Spike made a similar clone of DP feature, Baker tried to port to ProQuake, I muddled existing Quake code to facilitate the same effect, based on DarkPlaces'.

        The 64 shots in the dark are (lordhavoc's random algorithm; LHRANDOM) shooting at random spots within the player's bounding box to get a hit.

        ClipMoveToEntity is an inherit Quake function used for clipnode testing for collisions, player, monster, etc. iirc.

        Editing the client to glow for null model quake players with quad is actually the easiest solution to code, but getting people to update their Quake client engine code, and asking players to download them seems like a big hurdle.
        It would be a SERVER-SIDE change, so only sysOps need to update the engine.

        Oddly, it is an expensive process, just in the chance that 1% of players connecting to a server use a wallhack; though one can make a wallhack in 2 api calls.

        sad.
        Last edited by R00k; 06-29-2015, 09:31 PM.
        www.quakeone.com/qrack | www.quakeone.com/cax| http://en.twitch.tv/sputnikutah

        Comment


        • #5
          Part #2, The hunt for perfection

          For cullentities, what a server does is draw a line straight between two players and looks for any walls. If a wall is found, then the server will hide the players from each other. There can be more than one line test used. In the code I started with, the runequake server code, there are more lines drawn from the viewer to each "corner" of another player (since the players are technically boxes). This is 8 more line tests, and they usually allow a partially obscured player to still be seen. R00k's code above has the normal line test, one "super" line test, and 64 more random offset line tests, which is pretty damn good coverage.

          Like I said above, at the dmtx server, this entire testing procedure is skipped if a viewed player has quad/pent. It's as if cullentities was not being used on such a player. I like to think there is a perfect solution that allows cullentities and yet allows quad to glow through walls. I will explain some ideas I had, and why they failed. Your eyes may glaze over soon, if they haven't already at this point.

          The first idea was to make the server send players with blank/nothing models instead of hiding them completely. As r00k and I found, quake clients, like Proquake and Qrack (I assume) skip things with blank models, even if there is supposed to be a glow. This is client behavior, and not server controlled. Implementing this code change would be easy, but everyone would be required to update their clients (to glow blank entities) along with server hosts being required to update their cullentities code.

          Thinking about it again, it's likely a dedicated wallhack designer (are there any?) could mess around with a reportedly blank player model. Such as: recreating the player model to be seen through a wall. The idea was already logistically bad enough; it didn't need a mode of failure, too!

          Anyway, a few days ago, I thought of a solution where a line test is done from a certain distance away, instead of exactly from a quad holding player. This point would then be sometimes on the other side of a wall, perhaps in a room where a viewing player is. In this case, the line test would trace from this new point to the player without meeting a wall. Theoretically, the test shows there is a clear line of sight, and cullentities can be skipped. (This means the player with quad behind the wall is shown, and thus the glow would be rendered through the wall like it used to.)

          Since the quad glow seems to be about 80 Quake units, this new point should be 80 units away. So, if the wall is thicker than 80 units, or the quad holder is far enough away from a thin wall, the testing point starts from within the wall and fails. (This means cullentities is used, and the player is hidden, even when holding quad! Success.) Really, there does need to be a point 80 units to the left and another point 80 to the right... and another in front, behind, up, and down... just to be sure, since the wall can be any side during gameplay.

          Six tests is not a bad cost at all, but there are limitations. 80 units is not that long, but it is possible the point reaches into the NEXT wall in a room or corridor. In this case, cullentities is used when it should not be, since the line test plainly detects a wall. Additionally, due to geometry, angled walls can provide such false positives pretty easily. So, we can add more points: perhaps some points for each 8 corners... (the glow is a sphere, so we need some amount less than 80) and then maybe another entire group 40 away... As you can see, the idea starts becoming unwieldy and begs for a better solution.

          Idea #2 I thought was clever, at first. Why not use a line from a viewing player exactly towards a quad holding player until we meet a wall. If this point on the wall is within 80 units of the quad player, then it is within the glow, and there would be a glow there, thus the player should not be hidden to enable the glow on the wall.

          The problem here comes from the possibility that a wall that should have a glow could have a different thickness than the wall on which the line stops. [This would be easy to demonstrate in a drawing, but not in text, so bear with me.] Note that the wall between the quad and the pent window in dm3 is thin and basically straight, but the quad does not actually sit in an a regular square corner with this wall. There is a small, angled wall in this corner, creating a thicker wall section. In the situation where a quad holder is on the quad item point, my so-called clever test will fail when another player is far enough back in the pent window room. To such a viewer, the thin wall should have a glow "up ahead" (when facing the doorway to quad), but the line goes through the thicker wall instead.

          I finally gave in and tried searching the internet for a solution. The quad glow is basically spherical (especially in darkplaces), so the problem I am solving is "Can a sphere of this size be seen by a player from this point in the map?". A google search showed me people have looked for this solution before me. However, solutions seem to always requires use of the video card. (One neat example is to draw everything in white, then give the graphics card a sphere of a certain color at a certain point in the map. Next, you can search the screen for this color to see if the card found any point the sphere should be visible.) Quake servers do not use the graphics card in any method beyond displaying text. (Yes, -listen type servers do use graphics, but no one runs that type of server.) Anyway, it's not an option for us.

          (tl;dr) I was hoping to end this with a solution, but I haven't found one yet.

          Comment


          • #6
            Good research Zop, interesting read. I have emailed LH your video but not yet heard an answer. Would be interesting hearing his feedback, but he tends not to come to this site often.

            Comment


            • #7
              Originally posted by Cobalt View Post
              Good research Zop, interesting read. I have emailed LH your video but not yet heard an answer. Would be interesting hearing his feedback, but he tends not to come to this site often.
              he can readily be found on QuakeNet IRC, sometimes even on GameSurge IRC.
              Want to get into playing Quake again? Click here for the Multiplayer-Startup kit! laissez bon temps rouler!

              Comment


              • #8
                Six tests is not a bad cost at all, but there are limitations. 80 units is not that long, but it is possible the point reaches into the NEXT wall in a room or corridor. In this case, cullentities is used when it should not be, since the line test plainly detects a wall. Additionally, due to geometry, angled walls can provide such false positives pretty easily. So, we can add more points: perhaps some points for each 8 corners... (the glow is a sphere, so we need some amount less than 80) and then maybe another entire group 40 away... As you can see, the idea starts becoming unwieldy and begs for a better solution.
                Well, you can combine previous approaches, here, specifically the "shotgun" approach on this sphere. Use this radius 80 sphere, but pick a number of points at random within it, and is any one of those is visible, then display it. 64 might be a reasonable number for a HULL1 entity (56x32x32), but to retain the same density of coverage for a radius 80 sphere (2144560 qu3) would require nearly 2400 tests. That's somewhat unreasonable, but perhaps that density is not really required?

                You could do some analysis involving how much of that sphere pokes through the wall at different distances away from the other side, but that would require being able to work out the volume of specific subsections of a sphere; the last time I tried to work out how to do this, however, I ended up having a rather large arguement with someone over IRC, something which I would rather not repeat...
                Intelligence is knowing that there is an 'i' in "community".
                Wisdom is knowing that there is no 'i' in "community".

                Comment


                • #9
                  Originally posted by yesterday View Post
                  Well, you can combine previous approaches, here, specifically the "shotgun" approach on this sphere. Use this radius 80 sphere, but pick a number of points at random within it, and is any one of those is visible, then display it. 64 might be a reasonable number for a HULL1 entity (56x32x32), but to retain the same density of coverage for a radius 80 sphere (2144560 qu3) would require nearly 2400 tests. That's somewhat unreasonable, but perhaps that density is not really required?

                  You could do some analysis involving how much of that sphere pokes through the wall at different distances away from the other side, but that would require being able to work out the volume of specific subsections of a sphere; the last time I tried to work out how to do this, however, I ended up having a rather large arguement with someone over IRC, something which I would rather not repeat...
                  I hate that an argument occurred over this,even more if it was related to this stuff directly.

                  I thank you for your post that I have no clue what its talking about, and pray some one else does haha.
                  Want to get into playing Quake again? Click here for the Multiplayer-Startup kit! laissez bon temps rouler!

                  Comment


                  • #10
                    Interesting, yesterday. I assume finding the volume that pokes out of a wall has some gross geometry with a wall plane, but is technically possible. I guess the problem is still "can the player see it from point X", but at least the shotgun approach becomes more reasonable.

                    Thinking on it again, I know we can actually exclude the half of the sphere on the far side of the player from a viewer. We'd need to get vectors always pointed towards the viewer from the quad holder, but at least only half of the 2400 tests are necessary. There's still a long way to go, even if we halve the density at this point.

                    Comment


                    • #11
                      I'm not sure about gross geometry, more stuff that I'd have to sit down and stare at for a while.

                      If you're excluding the "far side of moon", as it were, then when choosing random points in the sphere, assuming randomvec() or the engine-side equivalent, then you can just test the dotproduct of enemy to selected point and enemy to self, and if that's negative, then invert the selected point with respect to the enemy (so that the dotproduct will be positive). That will save you from rejecting any more points than the ~47.6% that randomvec() already rejects.

                      Mindz: Not exactly this, but it was related to randomvec(); specifically, the way that DPmod uses randomvec() for shotgun spreads, which I feel makes them too accurate at longer ranges. I can explain the function in question and what I was trying to calculate in more detail, if you would like.
                      Intelligence is knowing that there is an 'i' in "community".
                      Wisdom is knowing that there is no 'i' in "community".

                      Comment


                      • #12
                        Originally posted by yesterday View Post
                        I'm not sure about gross geometry, more stuff that I'd have to sit down and stare at for a while.

                        If you're excluding the "far side of moon", as it were, then when choosing random points in the sphere, assuming randomvec() or the engine-side equivalent, then you can just test the dotproduct of enemy to selected point and enemy to self, and if that's negative, then invert the selected point with respect to the enemy (so that the dotproduct will be positive). That will save you from rejecting any more points than the ~47.6% that randomvec() already rejects.

                        Mindz: Not exactly this, but it was related to randomvec(); specifically, the way that DPmod uses randomvec() for shotgun spreads, which I feel makes them too accurate at longer ranges. I can explain the function in question and what I was trying to calculate in more detail, if you would like.
                        The only thing I would understand (in all likelihood) would be the spread of the shotgun hah. I'm just glad you are pitching in to tackle this quad glow thing, because as it stands its definitely flawed.
                        Want to get into playing Quake again? Click here for the Multiplayer-Startup kit! laissez bon temps rouler!

                        Comment


                        • #13
                          I dont know too much about the lightmap, but DP does have a getlight () float builtin that can successfully bring back I believe a rgb vector representation of the light. I have tested this to work on local servers but on dedicated servers LH has not made it possible yet to load the lightmap. I was curious, if we picked locations inside that wall which is now I guess "transparent", would we get the rgb vector of the quad glow, or would the engine still see the wall as solid on the server side and return maybe no lightlevel, or a smaller fractional value of the quad glow? The lightmap I believe is only loaded once every level....?

                          Originally posted by yesterday View Post
                          You could do some analysis involving how much of that sphere pokes through the wall at different distances away from the other side, but that would require being able to work out the volume of specific subsections of a sphere; the last time I tried to work out how to do this, however, I ended up having a rather large arguement with someone over IRC, something which I would rather not repeat...

                          Comment


                          • #14
                            Originally posted by Zop View Post
                            We'd need to get vectors always pointed towards the viewer from the quad holder, but at least only half of the 2400 tests are necessary. There's still a long way to go, even if we halve the density at this point.
                            Very true. How about 100? (Screw trying to work it out properly, I'm doing it Monte Carlo style.)

                            To arrive at that number, I first transferred randomvec() into Perl, which basically meant having to fake the floating point version of random() that the QCVM provides (most RNGs are 0<=x<1; Quake's is 0<=x<=1). Once there, it's just a case of doing enough tests to get a reasonable feel for the probability.
                            Code:
                            #!/usr/bin/perl
                            
                            use warnings;
                            
                            my $precision = 10000;
                            my $cprec = $precision * 2 + 1;
                            
                            my $attempts = 0;
                            my $calls = 0;
                            my $counting = 0;
                            
                            while ($attempts < 1000000) {
                            
                            	my $x = (int(rand($cprec))-$precision)/$precision;
                            	my $y = (int(rand($cprec))-$precision)/$precision;
                            	my $z = (int(rand($cprec))-$precision)/$precision;
                            
                            	my $distsq = $x*$x + $y*$y + $z*$z;
                            	++$calls;
                            
                            	unless ($distsq > 1) {
                            #		print "$x $y $z $distsq\n";
                            		++$attempts;
                            
                            		if ($x >= 0.80) {
                            			++$counting;
                            		}
                            	}
                            }
                            print "$counting hits from $attempts shots\n";
                            print "$calls calls to randomvec() for $attempts attempts\n";
                            print "pi is approximately " . 6*($attempts/$calls) . "\n";
                            $precision is how fine-grained the floats are; to be true to the Quake engine, I believe that this should be 32767, but you should be fine as long as it's sufficiently high. The rest should be fairly obvious. Change the number in the while loop to do more tests, and change the comparison in the heart of the loop to make less of the sphere visible.

                            With the settings as given, it measures the chances of seeing a sphere that is poking out of a flat wall by 16 units (somewhat arbitrary, but I had to start somewhere). And I get this result from a large run:
                            2799890 hits from 100000000 shots
                            191026792 calls to randomvec() for 100000000 attempts
                            pi is approximately 3.14092067253058
                            The chance to hit is basically 2.8%. (The other lines aren't relevant, but they were interesting to me when I was working on this.)

                            A 2.8% chance to hit with any given shot means a 97.2% chance to miss. We want to make enough shots so that the chance of missing completely is quite low. Assuming that you're aiming for a 95% success rate (hitting at least once), you need at least log(0.05)/log(0.972) = 105.486 shots. This of course assumes that you're shooting at the whole sphere, and not just the near half. So you either need less than that, or you can hit a smaller area with that reliability.

                            I'm assuming that you're running this check every frame, which may mean that the glow might flicker slightly, but I don't think that that's much of a problem. I'd still be checking the 6 axial edge points as well, though, as those are going to make this test obselete in the vast majority of cases. But it will help to catch the more obscure situations reliably enough.
                            Intelligence is knowing that there is an 'i' in "community".
                            Wisdom is knowing that there is no 'i' in "community".

                            Comment


                            • #15
                              This sounds promising. What's that log conversion called? It reminds me of switching bases.

                              Comment

                              Working...
                              X