Adding a Scope: Difference between revisions
Zoolicious (talk | contribs) No edit summary |
Zoolicious (talk | contribs) No edit summary |
||
Line 202: | Line 202: | ||
} | } | ||
</pre> | </pre> | ||
...and that | |||
== Making a Weapon Zoom == | |||
I got a request to add a section about actually adding zoom functionality to a weapon in the first place. I could post a full code tutorial for this, but it's not really necessary, because the code for CWeaponCrossbow does exactly this and is very easy to understand. However, I discuss roughly what you need to do below; reading this in conjunction with looking at the relevant CWeaponCrossbow functions should allow you to add zooming to your weapon without any trouble. | |||
To a very basic weapon (say the .357 Magnum), you need to add one boolean field and 5 new functions to acheive the zoom function like the crossbow. Bare in mind that many weapons (like the pistol) alreday define one or more of these functions, and all you need to do is add to it. | |||
<pre> | |||
bool m_bInZoom; // Set to true when you are zooming, false when not | |||
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); // Required so that you know to un-zoom when switching weapons | |||
void ItemPostFrame( void ); // Called every frame during normal weapon idle | |||
void ItemBusyFrame( void ); // Called when the weapon is 'busy' e.g. reloading | |||
void ToggleZoom( void ); // If the weapon is zoomed, un-zoom and vice versa | |||
void CheckZoomToggle( void ); // Check if the secondary attack button has been pressed | |||
</pre> | |||
Just copy the relevant code from those crossbow functions into these functions in your new zooming weapon. That should be enough to control zooming for any weapon. Add to that (in the ToggleZoom() function) the scope code discussed above and hey presto - a weapon with a zooming scope. | |||
Andy aka zoolicious | Andy aka zoolicious |
Revision as of 10:33, 12 February 2006
You can use the code and ideas in this tuorial to add a HUD-based sniper scope to your game, for use by any weapon that you see fit :) As an example, I've added it alongside the existing zoom functionality of the HL2 crossbow, but as you'll see, you can tell it to display from any part of your code.
Prerequisites
The only prerequisite for this tutorial is that you have already created a sniper scope texture (e.g. a big black square/rectangle with a transparent circle in the middle of it) which has an appropriate .VMT file. Here's one I made earlier:
...you also need to setup this material to be loaded as a hud texture; do this by adding the following to scripts/hud_textures.txt
"sprites/640_hud" { TextureData { "scope" { "file" "scope" "x" "0" "y" "0" "width" "512" "height" "512" } ... } }
The HUD Element
This element displays your scope texture on the HUD. Just add the following code to hud_scope.cpp, which you should create somewhere in your game's client project.
#include "cbase.h" #include "hudelement.h" #include "hud_macros.h" #include "iclientmode.h" #include "c_basehlplayer.h" #include <vgui/IScheme.h> #include <vgui_controls/Panel.h> // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" /** * Simple HUD element for displaying a sniper scope on screen */ class CHudScope : public vgui::Panel, public CHudElement { DECLARE_CLASS_SIMPLE( CHudScope, vgui::Panel ); public: CHudScope( const char *pElementName ); void Init(); void MsgFunc_ShowScope( bf_read &msg ); protected: virtual void ApplySchemeSettings(vgui::IScheme *scheme); virtual void Paint( void ); private: bool m_bShow; CHudTexture* m_pScope; }; DECLARE_HUDELEMENT( CHudScope ); DECLARE_HUD_MESSAGE( CHudScope, ShowScope ); using namespace vgui; /** * Constructor - generic HUD element initialization stuff. Make sure our 2 member variables * are instantiated. */ CHudScope::CHudScope( const char *pElementName ) : CHudElement(pElementName), BaseClass(NULL, "HudScope") { vgui::Panel *pParent = g_pClientMode->GetViewport(); SetParent( pParent ); m_bShow = false; m_pScope = 0; // Scope will not show when the player is dead SetHiddenBits( HIDEHUD_PLAYERDEAD ); } /** * Hook up our hud message, and make sure we are not showing the scope */ void CHudScope::Init() { HOOK_HUD_MESSAGE( CHudScope, ShowScope ); m_bShow = false; } /** * Load in the scope material here */ void CHudScope::ApplySchemeSettings( vgui::IScheme *scheme ) { BaseClass::ApplySchemeSettings(scheme); SetPaintBackgroundEnabled(false); SetPaintBorderEnabled(false); if (!m_pScope) { m_pScope = gHUD.GetIcon("scope"); } } /** * Simple - if we want to show the scope, draw it. Otherwise don't. */ void CHudScope::Paint( void ) { if (m_bShow) { // This will draw the scope at the origin of this HUD element, and // stretch it to the width and height of the element. As long as the // HUD element is set up to cover the entire screen, so will the scope m_pScope->DrawSelf(0, 0, GetWide(), GetTall(), Color(255,255,255,255)); } } /** * Callback for our message - set the show variable to whatever * boolean value is received in the message */ void CHudScope::MsgFunc_ShowScope(bf_read &msg) { m_bShow = msg.ReadByte(); }
Then you need to declare your HUD element in scripts/HudLayout.res with the following lines:
HudScope { "fieldName" "HudScope" "xpos" "0" "ypos" "0" "wide" "640" "tall" "480" "visible" "1" "enabled" "1" "PaintBackgroundType" "0" }
This will make the element cover the entire screen.
Telling the HUD Element When to Show
For this, I used a HUD (aka User) message which I called ShowScope. To enable this, add the following line to your user messages registration code (e.g. hl2_usermessages.cpp or similar), in the RegisterUserMessages() function:
usermessages->Register( "ShowScope", 1); // show the sniper scope
Then all you need to do is fire off this message with either a true or false value (1 or 0) to show or hide the scope. For example, change the CWeaponCrossbow::ToggleZoom() function to the following:
void CWeaponCrossbow::ToggleZoom( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return; if ( m_bInZoom ) { if ( pPlayer->SetFOV( this, 0, 0.2f ) ) { m_bInZoom = false; // Send a message to hide the scope CSingleUserRecipientFilter filter(pPlayer); UserMessageBegin(filter, "ShowScope"); WRITE_BYTE(0); MessageEnd(); } } else { if ( pPlayer->SetFOV( this, 20, 0.1f ) ) { m_bInZoom = true; // Send a message to Show the scope CSingleUserRecipientFilter filter(pPlayer); UserMessageBegin(filter, "ShowScope"); WRITE_BYTE(1); MessageEnd(); } } }
Making a Weapon Zoom
I got a request to add a section about actually adding zoom functionality to a weapon in the first place. I could post a full code tutorial for this, but it's not really necessary, because the code for CWeaponCrossbow does exactly this and is very easy to understand. However, I discuss roughly what you need to do below; reading this in conjunction with looking at the relevant CWeaponCrossbow functions should allow you to add zooming to your weapon without any trouble.
To a very basic weapon (say the .357 Magnum), you need to add one boolean field and 5 new functions to acheive the zoom function like the crossbow. Bare in mind that many weapons (like the pistol) alreday define one or more of these functions, and all you need to do is add to it.
bool m_bInZoom; // Set to true when you are zooming, false when not bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); // Required so that you know to un-zoom when switching weapons void ItemPostFrame( void ); // Called every frame during normal weapon idle void ItemBusyFrame( void ); // Called when the weapon is 'busy' e.g. reloading void ToggleZoom( void ); // If the weapon is zoomed, un-zoom and vice versa void CheckZoomToggle( void ); // Check if the secondary attack button has been pressed
Just copy the relevant code from those crossbow functions into these functions in your new zooming weapon. That should be enough to control zooming for any weapon. Add to that (in the ToggleZoom() function) the scope code discussed above and hey presto - a weapon with a zooming scope.
Andy aka zoolicious