制作CS作弊器的教程(透视 白墙 框架模式 高亮 去除烟幕,闪光,天空 自设准心)
This How-To is for experienced programmers who need to know how they can implement those basic features into their hack. I won't give much code here because if you are a programmer, you can work it out yourself where to put it etc... ?Feature #1: Transparent walls
In your hooked glBegin, check if the mode is GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN or GL_QUADS. If it is not, Half-Life wants to draw a wall and we want to make the walls transparent so firstly we want to know the current color:
glGetFloatv(GL_CURRENT_COLOR, &curcol)
We now have the color as float-values with single precision which equals 32 bits or 4 bytes each. They're arranged as follows:
curcolor[0] = red portion
curcolor[1] = green portion
curcolor[2] = blue portion
Secondly, we want to use blending instead of depth-testing, so we turn one thing off and the other on:
glDisable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
Thirdly, we have to choose the desired blend-mode:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
I used this combination in my OpenGL Hack because I think this looks best. You can experiment other combinations. Valid constants are:
GL_ZERO
GL_ONE
GL_SRC_COLOR
GL_ONE_MINUS_SRC_COLOR
GL_SRC_ALPHA
GL_ONE_MINUS_SRC_ALPHA
GL_DST_ALPHA
GL_ONE_MINUS_DST_ALPHA
GL_DST_COLOR
GL_ONE_MINUS_DST_COLOR
GL_SRC_ALPHA_SATURATE
Finally, we can choose how transparent we want the walls (also called alpha-value). For my Hack i used 0.5 ! Since we don't want to mess up the colors, we use the rgb-values from before:
glColor4f(curcol[0], curcol[1], curcol[2], 0.5f)
Basically, we have transparent walls now. But we won't have much fun with it as long as we don't clear the color-buffer and the depth-buffer after every frame to prevent the frames being blended into each other and messing up our graphics. There are several ways how to do that, but only one way I know of which doesn't kill the HL-screenshot feature.
You have to hook glClear and check if the given parameter is GL_DEPTH_BUFFER_BIT. If so, add GL_COLOR_BUFFER_BIT to it first. Next step is to set the color it should be cleared with to black or white ... otherwise everything has a red tint because red is the standard clear-color in HL.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
Now you can call the original glClear function.
That's it!
To see what the different OpenGL-modes mean, take a look > here <
?Feature #2: White walls
Again, we check in glBegin for GL_TRIANLGES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN or GL_QUADS. If it is not, we make the following simple call:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
That will remove any texture from every wall, making it bright white.
?Feature #3: Wireframe mode
In glBegin we check the mode to be GL_POLYGON and if it is, we want it to be wireframed with lines of one pixel width:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glLineWidth(1.0)
Now we can set the lines to a nice green color like that:
glColor3f(0.0f, 0.7f, 0.0f)
After that, we're finished and can call the original glBegin.
Last thing to do: If the mode is not GL_POLYGON :
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
This will turn off wireframe for everything which is not drawn in GL_POLYGON, like player models.
Remember that this wireframe mode also requires the buffer being cleared between the frames, so modify glClear as shown in Feature #1.
?Feature #4: Lambert only
The feature called "Lambert" will prevent models from being shaded, so you will see all players and items in full brightness even when they're lying/standing in a dark corner. In order to achieve that effect, hook glVertex3f and do the following before passing it to the original function:
glColor3f(1.0f, 1.0f, 1.0f)
?Feature #5: Smoke removal
This one is actually very easy and I can't understand why some people use the HL-engine function HUD_AddEntity for this task. All you have to do is to hook glBegin and glVertex3fv and define a flag bSmoke. Inside glBegin, check for GL_QUADS and if TRUE, retrieve the current color:
glGetFloatv(GL_CURRENT_COLOR, &curcol)
Now we can easily determine if HL wants to draw smoke by checking for a grey color in curcol. Grey means red = green = blue . One last thing is to exclude 1.0 and 0.0 , which is not used for drawing smoke but for drawing various things in VGUI. So if the current color is grey and not 1.0 or 0.0 , we set bSmoke to TRUE and that's it for glBegin. In all other cases, set bSmoke to FALSE!!
Now in glVertex3fv, we check for bSmoke to be true and if so, we return to the caller without calling the original glVertex3f function!
Et voil?
?Feature #6: Flashbang removal
This one needs two hooked functions: glBegin and glVertex2f.
HL draws simple quads like console, VGUI etc with Vertex2f... also the flashbang effect which is one simple quad drawn over the whole screen with pure white color. When the effect goes away you see the original screen fading in. So obviously, HL is modifying the alpha-value to blend the white quad together with the normal view. So we just check for a white quad with the coordinates of the screen and set minimum alpha again... There we go:
In glBegin, we check mode for GL_QUADS. If so, we fetch the current color:
glGetFloatv(GL_CURRENT_COLOR, &curcol)
Now we look for pure white, which means red = 1.0, blue = 1.0 and green = 1.0 ... if it is, there's a high chance that a flashbang is drawn. Unfortunately we cannot be sure because I noticed some VGUI things are also called with pure white so we have to choose another way. When an OpenGL-application calls glBegin it has to call one of the glVertex-functions afterwards for each coordinate of the object to be drawn. When the object is complete, it calls glEnd. We know that HL draws simple quads with glVertex2f so we will also hook that function.
In order to communicate between glBegin and glVertex2f, we have to use a flag (boolean datatype) to indicate a white quad. So if we encounter pure white above, we just set the flag (lets call it bFlash) to 1 which equals TRUE.
The next step is to retrieve the current screen dimensions since we need them to compare with the quad to be drawn. So before or after we set bFlash to TRUE, we do:
glGetFloatv(GL_VIEWPORT, &coords)
Which saves the screen size into coords:
coords[0] = 0
coords[1] = 0
coords[2] = width
coords[3] = height
Last thing to do in glBegin is: in case the quad is not white we have to set bFlash to FALSE (0) !
Now in our hooked glVertex2f, we firstly look for bFlash being 1 ... if not, we call the original function. But if bFlash is set to TRUE, we compare the second given parameter (y-coordinate) to the screen-height (which is in coords[3]). If those two match, HL wants to draw the flashbang quad ... or the console as long as it is in full-screen! That's not really a problem, because when the console is drawn over the whole screen, there's nothing behind it ... so it is safe to just set the alpha value to minimum (equals maximum transparency), which won't affect console, but makes the flashbang effect go away:
glColor4f(curcol[0], curcol[1], curcol[2], 0.01f)
?Feature #7: Sky removal
This feature is only useful when used together with transparent walls or wireframe because the sky is irritating in those modes. It involves two functions: glVertex3f and glBegin
So the first step is to hook those functions. Next step is to define another boolean variable, let's call it bSky. Now in glBegin, the only thing to do is to check for GL_QUADS and set bSky to TRUE (1) and then calling the original function. Else, set bSky to FALSE.
In glVertex3fv, just check for bSky to be true and if so, return to the caller without calling the original glVertex3f function.
Please remember that "smoke removal" also uses glVertex3f so make sure that those two won't interefere with each other. I solved that by checking for bSmoke first if it's TRUE and only if it is not, I check for bSky.
?Feature #8: XQZ-style wallhack (model-hack)
In glBegin, check for GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN. If one of those two modes are used, HL wants to draw a model (player, item, ...), so we do:
glDisable(GL_DEPTH_TEST)
... which is telling OpenGL to skip the testing whether you can see an object based on other things which are possibly nearer to you. But if glBegin is not called with those two modes, turn depth-testing on to make sure you don't affect other objects:
glEnable(GL_DEPTH_TEST)
?Feature #9: Extra Crosshair
There are probably many ways to find a place for drawing your own things, but I chose glEnable. Start by defining a boolean... let's call it bDrawn. That boolean should be set to 1 (TRUE) in glEnable after you've drawn everything and set it to 0 (FALSE) in glViewport because HL calls that function before every frame!
So far so good ... now in glEnable check for bDrawn to be FALSE (0) and if not, just call the original function. If it is 0, you can add the drawing code embedded like the following:
glPushMatrix()
glLoadIdentity()
glDisable(GL_TEXTURE_2D)
<< your draw code here >>
glEnable(GL_TEXTURE_2D)
glPopMatrix()
This ensures that you don't touch the current matrix with all the information of the other models etc.
The code of my crosshair used since v1.7 of the OpenGL Hack is the following:
glGetIntegerv(GL_VIEWPORT, &iDim)
glColor4f(1.0f, 0.0f, 1.0f, 1.0f)
glLineWidth(3.0f)
glBegin(GL_LINES)
glVertex2i(iDim[2]/2, (iDim[3]/2)-12)
glVertex2i(iDim[2]/2, (iDim[3]/2)-5)
glVertex2i(iDim[2]/2, (iDim[3]/2)+5)
glVertex2i(iDim[2]/2, (iDim[3]/2)+12)
glVertex2i((iDim[2]/2)-12, iDim[3]/2)
glVertex2i((iDim[2]/2)-5, iDim[3]/2)
glVertex2i((iDim[2]/2)+5, iDim[3]/2)
glVertex2i((iDim[2]/2)+12, iDim[3]/2)
glEnd()
glColor3f(1.0f, 0.0f, 0.0f)
glBegin(GL_POINTS)
glVertex2i((iDim[2]/2)-3, iDim[3]/2)
glVertex2i((iDim[2]/2)+3, iDim[3]/2)
glVertex2i(iDim[2]/2, (iDim[3]/2)-3)
glVertex2i(iDim[2]/2, (iDim[3]/2)+3)
glEnd()
?Feature #10: Fullbright
What lambert does to models does fullbright to the walls: ignores shadows so you will see the wall/ceiling in full brightness! All you have to do is to define a flag (let's call it bTex) and to hook glBegin, glEnable and glDisable.
Shadows are drawn with black textures which are blended over the walls and which are more or less transparent, depends on how dark the map designer wants them to be. So the goal is easy to guess: determine when HL draws walls with textures and turn texturing off. There we go: In glEnable we check for GL_TEXTURE_2D as mode and if so, we set our flag bTex to be TRUE (1). In glDisable we're setting bTex to FALSE (0) if the mode is GL_TEXTURE_2D.
Now we know if HL wants to draw textured objects, so the last thing to do is in glBegin: We check for walls, so like in features #1 and #2 we check the mode to be GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN or GL_QUADS. If not, we know that HL will draw the walls now so we just check bTex to be TRUE and if it is, we finally do:
glDisable(GL_TEXTURE_2D)
Mission accomplished!