Posted by: drnelson
Date posted: Jan 25 2005 User Rating: 4.5 out of 5.0 | Number of views: 5539 Number of comments: 4 | Description: I missed the zooming feature of the 357 that was in HL1 so I thought as a beginner tutorial I'd write a weapon zooming lesson. I then carried it out to a 3-stage zoom. This is for beginners and anyone curious as to my methods. |
About Me: I, like many others, am also new to the Half-Life 2 SDK scene. I did a lot of playing around in Half-Life's SDK's but this seems to be a whole new world. This article reflects what I have learned and are not the words of a Valve certified programmer. So if there are any issues please let me know right away and I will fix them as soon as possible. However, on that same note. I have tested this tutorial several times and it does work. So thanks for reading and I hope you enjoy it. -- David Nelson
About this Article: This article is mainly for beginners. I have taken what I have learned from the crossbow and applied it towards the 357. I then created a 3 stage zooming feature. The method I use for the zoom keeps the option of a secondary attack open and a zoom key is easy to implement. (More on this later) This method can be applied to any weapon that doesn't have a secondary fire action with ease. Whenever I modify a file I add a little comment tag: // MOD so I can look back at all the files I modified by just doing a CTRL+SHIFT F and searching for MOD in my files. I hope this clears up any weird comments you will see in my code.
How the Zoom Works It is always important to know how something works before you implement it. So to start off I suggest opening basecombatweapon_shared.cpp (in server (hl->source files)) and hit CTRL-F and search for | | | | CBaseCombatWeapon::ItemPreFrame |
CBaseCombatWeapon is the base class that our weapons are derived from. The function's ItemPreframe(), ItemPostFrame(), ItemHolsteredFrame() are very important to us because the game calls these functions once every frame. If we check if the secondary attack key was pressed during these times we can achieve a smooth, quick, and reliable zooming function.
For more information about the CBaseCombatWeapon I suggest reading Josiwe's excellent article: An Exploration Of Weapon_RPG: Part 1A
I mentioned the above because for the 357 we will be adding those functions to our code. Other weapons already use some of these functions but the 357 does not. What we are actually doing is overriding the base classes functions and then calling those base functions after our code. (If you're confused just ignore all this)
So the basic idea is that when the functions are called after, before, or in between frames we will check to see if the player pressed the +attack2 key. If he did we will enter into our zoom function. It will check to see if we are already zoomed in. If we are and we are not zoomed in all the way, then we will zoom in all the way. If we are already zoomed in all the way we will go back to the normal view. (We are actually changing the players Field Of View or FOV for short. After this is implemented we need to be careful that we have some method to reset the view back to normal. To do this we will implement a function to reset the FOV when we holster (switch or run out of ammo) the firearm. This will stop the FOV from staying permantly zoomed in.
Implementation First we need to open weapon_357.cpp which is located in: HL Server Code - Source Files - HL2 DLL and set your cursor under the #includes
We then add the following lines:
| | | #define NEXT_ZOOM_TIME 0.2f #define ZOOM_STATE_NORMAL 0 #define ZOOM_STATE_2X 1 #define ZOOM_STATE_4X 2
|
The first define just declares a time variable of type float that will stop the user from pressing the zoom to quickly. The next three create the three states of our zoom. Normal is normal FOV, 2X is half the way in, and 4X is the farthest zoom.
Next we go into the Class declaration. Here we need to add some new variables and functions. The function should look like this:
| | | class CWeapon357 : public CBaseHLCombatWeapon { DECLARE_CLASS( CWeapon357, CBaseHLCombatWeapon ); public:
CWeapon357( void );
void ItemPostFrame( void ); void ItemBusyFrame( void ); void ItemHolsterFrame( void );
void PrimaryAttack( void ); void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
DECLARE_SERVERCLASS(); DECLARE_DATADESC();
private:
void CheckZoom( void );
int m_iZoomState; float m_flNextZoomTime; };
|
The changes are marked with comments. Here we just add our functions that will be called after every frame. We will use these to check our zoom states and reset the FOV. Also we added the CheckZoom() function so we can check our zoom state and change our FOV appropriately.
Now we need to register our variables we created in the macros. (I honestly am not sure if that is what we are doing exactly. But from what I've learned in the SDK we need to do this)
| | | BEGIN_DATADESC( CWeapon357 ) DEFINE_FIELD( m_iZoomState, FIELD_INTEGER ), DEFINE_FIELD( m_flNextZoomTime, FIELD_FLOAT ), END_DATADESC()
|
I hope to learn more about why we have to do that exactly but as of right now I appologize for not knowing. If anyone knows please leave a comment or leave me a message! Thanks!
Now we need to scroll down to the end of the file and add the functions we declared earlier:
| | | void CWeapon357::ItemBusyFrame( void ) { CheckZoom(); BaseClass::ItemBusyFrame(); }
void CWeapon357::ItemHolsterFrame( void ) { if (m_iZoomState != ZOOM_STATE_NORMAL) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); m_iZoomState = ZOOM_STATE_NORMAL; pPlayer->SetFOV(this, 0, 0.1f); } BaseClass::ItemHolsterFrame(); }
void CWeapon357::ItemPostFrame( void ) { CheckZoom();
BaseClass::ItemPostFrame(); }
|
We first implement ItemBusyFrame() so we can change our zoom even when we're reloading. We then implement ItemHolsterFrame() so that when the gun is switched or holstered the FOV is reset. We first check to see we are even zoomed in before we waste the time fixing the FOV. Last we add ItemPostFrame() because we want to check and see if the user has pressed the key to zoom.
Now we just need to implement our CheckZoom() Function:
| | | void CWeapon357::CheckZoom( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (pPlayer == NULL) return;
if ( (pPlayer->m_afButtonPressed & IN_ATTACK2) && (gpGlobals->curtime > m_flNextZoomTime) ) { m_flNextZoomTime = gpGlobals->curtime + NEXT_ZOOM_TIME; switch(m_iZoomState) { case ZOOM_STATE_NORMAL: m_iZoomState = ZOOM_STATE_2X; pPlayer->SetFOV(this, 20, 0.2f); break;
case ZOOM_STATE_2X: m_iZoomState = ZOOM_STATE_4X; pPlayer->SetFOV(this, 10, 0.2f); break;
case ZOOM_STATE_4X: m_iZoomState = ZOOM_STATE_NORMAL; pPlayer->SetFOV(this, 0, 0.2f); break; default: break; } } }
|
Here is a line by line explanation of my code above: First we get a handle to our player object so we can set the FOV. If this fails (the player is dead or some error) the function ends. Next we check and see if the +attack2 button was pressed (right mouse for most people). If it is we then check to see if the time is greater that the NextZoomTime. We do this so we don't zoom in and out too quickly. Also above I mentioned that it would be easy to transfer this code over to a key instead of the secondary attack. To do this you would just change the & IN_ATTACK2 to look for another key and you are free to setup a secondary attack function and still have a zoom. (Or you could just use valves 'z' key zoom thing. But where's the fun in that?) Next we set our m_flNextZoomTime to the current time plus our pre-defined time to slow the speed of the zoom change. We then enter our switch statement. We check the variable: m_iZoomState for 3 cases. The first case checks to see if we are at ZOOM_STATE_NORMAL. If so it switches the state to ZOOM_STATE_2X and changes the FOV to zoom in a little. (more on the SetFOV func in a second) If we were already in ZOOM_STATE_2X it puts us in ZOOM_STATE_4X and sets the FOV accordingly. And last, if we are at 4X it switches us back to normal and updates the FOV.
The pPlayer->SetFOV() function has three paramaters: 1.) CBaseEntity *pRequester - which is this in most cases. But it is the object that is requesting the FOV change. 2.) int FOV - the field of view amount we want to change 3.) float zoomRate - the rate of the zoom to occur. A large value here will make the zoom value slowly zoom in. A small value is more of a cutting from one view to the next.
That is our SetFOV function. Easy! That is also all of our modifications.
Conclusion I hope this helps someone dip their feet in. I did this as an experiment and had a lot of fun playing around with the many options. I plan on writing quite a few easier tutorials for the community unless people request that I don't. =) I do want to mention that this can easily be a copy and paste tutorial. And that's fine if that's what you really want to do. But if that is all you get from any tutorial you spent the time reading you need to start thinking outside the box and try and apply the tutorials to other aspects of the SDK. I hope you have enjoyed this tutorial and I hope it is well receieved. I have checked and double checked this tutorial for errors but something may have slipped past me. If so please let me know right away! Thanks for reading! -- David Nelson |
|
User Comments
Showing comments 1-4
I'd love to see some comments! And possibly rate my article with the rating system? I'm just curious as to what you think of it.
Thanks, David |
|
|
It's a nice tutorial, I thought no one would ever make one of these zooming tutorials again, but it's always a nice read, reminds me of my first adventures with the HL1 SDK ;) |
|
I think that this tutorial is very detailed and well written. Although the code is simple it teaches a lot.
QUOTE: I plan on writing quite a few easier tutorials for the community unless people request that I don't.
I don't think you need to write an easier tutorial. Every tutorial that is exlpaned like this one is easy |
|
|
Awesome stuff, these easy tuts are great for me. |
|
You must register to post a comment. If you have already registered, you must login.
|
296 Approved Articless
5 Pending Articles
3940 Registered Members
0 People Online (15 guests)
|
|