This tutorial is a step-by-step guide to creating a ‘VGUI Sniper Scope’. The maximum size of a sprite in Half-Life is 256x256 and to cover a screen you would need to tile it because you cannot stretch sprites. Combine the fact that you need to accommodate for each resolution the maths involved would be impossible to maintain. VGUI uses TGA images, then can be almost any size and you can change the opacity easily by using Photoshop. Ergo, a simple scope system that can look transparent, without looking odd and stretched. Open up your client workspace and create a new file called ‘vgui_scope.cpp’. This file will contain the initialising constructor and the update function. Add the following code:
| | | #include "hud.h" #include "cl_util.h" #include "vgui_TeamFortressViewport.h"
CScopePanel::CScopePanel(int x,int y,int wide,int tall) : Label("",0,0,ScreenWidth,ScreenHeight) { char sz[64];
sprintf( sz, "%i_scope", ScreenWidth );
Scope = LoadTGANoRes( sz ); }
void CScopePanel::Update() { setImage( Scope ); }
|
Before I move on, you must define the function ‘LoadTGANoRes’ under ‘vgui_CustomObjects.cpp’. Under ‘LoadTGAForRes’ add the following:
| | | BitmapTGA *LoadTGANoRes( const char* pImageName ) { BitmapTGA *pTGA;
char sz[256];
sprintf(sz, "gfx/vgui/%s.tga", pImageName);
pTGA = vgui_LoadTGA(sz);
return pTGA; }
|
The standard TGA loading code looks for two different images, either ‘640_X.tga’ or ‘320_X.tga’, depending on whether your resolution is greater than 640. The sniper scope needs to fill the entire screen so a custom image function needs to be coded allowing a certain image for a certain resolution. Therefore we need a separate TGA image for each resolution (Half-Life ranges from 640x480 to 1600x1200). I have uploaded an example TGA file (640x480) to my website, you can it here: Pongles.com The TGA file needs to be placed in your mod's gfx\vgui directory. Now close ‘vgui_CusomObjects.cpp’ and load up ‘vgui_TeamFortressViewport.h’, this where we are going to define our sniper class. Right at the top of the file you should see a lot of class definitions, add our scope class to them:
| | | class CScopePanel;
BitmapTGA *LoadTGANoRes(const char* pImageName);
|
The former line declares the scope class the latter declares the TGA loading image function we have used. Now add the following after the ‘CTFScrollPanel’ class definition:
| | | class CScopePanel : public Label { private: BitmapTGA *Scope; public: CScopePanel(int x,int y,int wide,int tall); void Update();
virtual void paintBackground() { // Do nothing, so the background's left transparent. } };
|
Still in the same file, find the class – ‘TeamFortressViewport’ (Line 412). Under ‘private’ definitions add the following:
| | | CScopePanel *m_pScopePanel;
|
Now under ‘public’ add the following:
| | | void CreateScope( void ); void ShowScope( void ); void HideScope( void );
|
We have now finished with ‘vgui_TeamFortressViewport.h’ so close it. You can now open up ‘vgui_TeamFortressViewport.cpp’ and find the following : ‘TeamFortressViewport::TeamFortressViewport(int x,int y,int wide,int tall) : Panel(x,y,wide,tall), m_SchemeManager(wide,tall)’ (Line 514) After ‘m_pClassMenu = NULL;’ add this:
After ‘CreateClassMenu();’ add this:
When ‘TeamFortressViewport’ is initialised the scope needs to be invisible so under the ‘Initialize’ function add the following (Line 595):
| | | if (m_pScopePanel) { m_pScopePanel->setVisible( false ); }
|
After the ‘TeamFortressViewport::CreateClassMenu()’ function (Line 1849) add the following:
| | | void TeamFortressViewport::ShowScope() { if (m_pScopePanel) { //m_pScopePanel->Open(); m_pScopePanel->setVisible( true ); } }
void TeamFortressViewport::HideScope() { if (m_pScopePanel) { m_pScopePanel->setVisible( false ); } }
void TeamFortressViewport::CreateScope() { // Create the panel m_pScopePanel = new CScopePanel(0, 0, ScreenWidth, ScreenHeight); m_pScopePanel->setParent(this); m_pScopePanel->setVisible( false ); m_pScopePanel->Update(); }
|
All the VGUI code is completed now. To make the scope appear and disappear you use these two functions: Use ‘gViewPort->HideScope();’ to hide the scope. Use ‘gViewPort->ShowScope();’ to show the scope. You could leave the tutorial now and use ‘HideScope’ and ‘ShowScope’ on your own. I have created an example on how to use them though. Close all your open windows and open up ‘ammo.cpp’. Find this line – ‘if ( gHUD.m_iFOV >= 90 )’ [ edit: This can be found in CHudAmmo::MsgFunc_CurWeapon -- Entropy ] and replace that entire if...else statement with the following:
| | | if ( gHUD.m_iFOV >= 90 ) { // normal crosshairs if (fOnTarget && m_pWeapon->hAutoaim) { SetCrosshair(m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255); } else { SetCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255); }
gViewPort->HideScope(); } else { // zoomed crosshairs if (fOnTarget && m_pWeapon->hZoomedAutoaim) { SetCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255); } else { SetCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255); }
gViewPort->ShowScope(); }
|
Good Luck!
Final note - in order to use the supplied tga file, you'll need to be running Half-Life in 640x480 resolution. |