Posted by: ScoBra7
Date posted: Apr 04 2003 User Rating: N/A | Number of views: 6539 Number of comments: 0 | Description: Introducing new functionality. |
In this tutorial we are going to add two new “key” functionalities. The first functionality is a “Fire Mode”; this is to switch the weapon’s fire mode from fire single, rapid and automatic mode. The second functionality is a “Zoom mode”. This enables zooming for most of the weapons. Actually it can be for all but it will not make sense to do it for, say, the crowbar. I will show you how to add new key binds and how to actually do these functionalities.
So let’s dive in and start coding. Open the server side workspace (mp). Open client.cpp and find the function void ClientCommand( edict_t *pEntity ). Go down a bit to:
| | else if (FStrEq(pcmd, "lastinv" )) { GetClassPtr((CBasePlayer *)pev)->SelectLastItem(); } |
Now insert after the curly brace (}) the following:
| | else if (FStrEq(pcmd, "firemode" )) { GetClassPtr((CBasePlayer *)pev)->ChangeFireMode(); } else if (FStrEq(pcmd, "zoommode" )) { GetClassPtr((CBasePlayer *)pev)->ChangeZoom(); } |
This function receives the client commands and processes it. The code that we inserted processes the two new commands, “firemode” and “zoommode”. As you can see each of the “else if” statements’ body calls a function in CBasePlayer.
Next find the function, void ClientPrecache( void ) and add | | PRECACHE_SOUND("items/airtank1.wav"); | This will be used in the zoom function. Save the file client.cpp.
Open player.h. Here we are going to define the two functions and a few others. At the top add the following after “#define PLAYER_H”:
| | //Fire modes #define MODE_SINGLE 0 #define MODE_RAPID 1 #define MODE_AUTO 2 #define ZOOM_NORMAL 0 #define ZOOM_1X 20 #define ZOOM_2X 10 #define FIREMODE_CHANGE_DELAY 0.5 |
This defines the fire - and zoom modes that we will use. It’s just a way to make the code more readable, rather than using the numerical values 0, 1 and 2.
Next find class CBasePlayer : public CBaseMonster and add the following:
| | void ChangeFireMode(void); void ChangeZoom(void); void SayFireMode(unsigned int iMode); float m_flNextFireModeTime; void ResetZoom(void); int m_fInZoom; |
The first two function definitions are used by the calls in client.cpp. The “SayFireMode” is use to display, on the HUD, what the selected fire mode is. The member variable “m_flNextFireModeTime” is used to de-bounce the keystroke, like in PrimaryFire etc. Next, the “ResetZoom” function does just that, it resets the zoom to zero. The member variable “m_fInZoom” are used to determine if we are zoomed (TRUE) or not (FALSE). You can use a bool rather than a float, it works better with MSVC 6. Just a note, for MSVC 6 rather also use the numeric 0 (zero) than NULL, the compiler will type cast the 0 better than the NULL. Save player.h
Open player.cpp. Find TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] = and add the following after the last DEFINE_FIELD statement:
| | DEFINE_FIELD( CBasePlayer, m_flNextFireModeTime , FIELD_TIME ), |
Next, find void CBasePlayer::Spawn( void ) and add the following somewhere in the function:
| | m_flNextFireModeTime = gpGlobals->time + FIREMODE_CHANGE_DELAY; m_fInZoom = FALSE; |
So when the player spawns the values will be set. m_flNextFireModeTime is set 0.5 seconds into the future and m_fInZoom is set to FALSE.
You can add the following anywhere, I’ve added this after DropPlayerItem function:
| | //ask current weapon to change fire mode and call say mode void CBasePlayer::ChangeFireMode(void) { if ( gpGlobals->time >= m_flNextFireModeTime) { m_flNextFireModeTime = gpGlobals->time + FIREMODE_CHANGE_DELAY; SayFireMode(m_pActiveItem->ChangeFireMode()); } }
//Display the fire mode void CBasePlayer::SayFireMode(unsigned int iMode) { if(m_iFOV == 0) { switch (iMode) { case MODE_SINGLE: { ClientPrint(this->pev, HUD_PRINTCENTER, "Single Fire",0,0,0,0); break; } case MODE_RAPID: { ClientPrint(this->pev, HUD_PRINTCENTER, "Rapid Fire",0,0,0,0); break; } case MODE_AUTO: { ClientPrint(this->pev, HUD_PRINTCENTER, "Automatic Fire",0,0,0,0); break; } } } }
//change the zoom mode void CBasePlayer::ChangeZoom(void) { if(m_pActiveItem->CanZoom(m_iFOV)) { EMIT_SOUND(ENT(pev), CHAN_BODY, "items/airtank1.wav", 0.5, ATTN_NORM); switch (m_iFOV) { case ZOOM_NORMAL: { m_fInZoom = TRUE; m_iFOV = ZOOM_1X; break; } case ZOOM_1X: { m_fInZoom = TRUE; m_iFOV = ZOOM_2X; break; } case ZOOM_2X: { m_fInZoom = FALSE; m_iFOV = ZOOM_NORMAL; break; } } } }
//Reset the zoom. void CBasePlayer::ResetZoom() { m_fInZoom = FALSE; m_iFOV = ZOOM_NORMAL; }
|
First, the function “ChangeFireMode” will check to see if the “global” time is larger than the time set to do the fire mode. If so, the next statement sets the fire mode time 0.5 seconds into the future. Thus the fire mode can only change after 0.5 seconds has elapsed. Next the call “SayFireMode(m_pActiveItem->ChangeFireMode());” consists of two parts. First the inner part “m_pActiveItem->ChangeFireMode()” will ask the current weapon to change it’s fire mode. We will define this later on. The return value is then fed to “SayFireMode”. A note here, it will be a good idea to check that m_pActiveItem != 0 before calling this function.
Second, the function “SayFireMode” takes an “unsigned int” as a parameter, which came from the previous function “ChangeFireMode”. What happens here is we first check to see if we are in a zoom mode. We will not display fire modes if we are zoomed. Next is a switch statement to see what we need to print on the HUD.
Third, the function “ChangeZoom”. Here we ask the current weapon if we can zoom “if(m_pActiveItem->CanZoom(m_iFOV))” we also supply the zoom factor so the weapon can store and use it if needed. Next we emit a sound, just for fun. Then a switch statement to do the next increment in the zoom.
Fourthly, the function “ResetZoom”. This just resets the zoom and is called by the weapons, that does do zooming, when reloading.
This is all for player.cpp so save it.
Next open weapons.h and find class CBasePlayerItem : public CBaseAnimating. Add the following function definitions:
| | virtual unsigned int ChangeFireMode(void){ return -1; }; //-1 if not implemented by weapon virtual bool CanZoom(int FOV) {return false;}; //false if not implemented by weapon |
So you do not have to change all the weapons, just the ones you want.
Right, I will use the MP5 to demonstrate this. So open mp5.cpp find class CMP5 : public CBasePlayerWeapon. In the public part add this: | | BOOL m_fInZoom;// don't save this. unsigned int ChangeFireMode(void); bool CanZoom(int FOV); void Holster( int skiplocal = 0 ); |
And in the private part add this: | | unsigned short m_usFireMode; int m_FOV; |
Add the following anywhere in the file after LINK_ENTITY_TO_CLASS( weapon_9mmAR, CMP5 ); : | | bool CMP5::CanZoom(int FOV) { if (FOV == ZOOM_2X) { m_fInZoom = FALSE; } else { m_fInZoom = TRUE; }
m_FOV = FOV; return true; }
void CMP5::Holster( int skiplocal /* = 0 */ ) { m_fInReload = FALSE;// cancel any reload in progress.
if ( m_fInZoom ) { m_pPlayer->ResetZoom(); } }
unsigned int CMP5::ChangeFireMode() { switch (m_usFireMode) { case MODE_SINGLE: { m_usFireMode = MODE_RAPID; break; } case MODE_RAPID: { m_usFireMode = MODE_AUTO; break; } case MODE_AUTO: { m_usFireMode = MODE_SINGLE; break; } } return m_usFireMode; }
|
“CanZoom” just saves the zoom factor and return true. “Holster” will be used to reset the zoom to zero when changing weapons. “ChangeFireMode” is the implementation of to change the fire mode.
Next find void CMP5::PrimaryAttack() and change the following from:
| | m_flNextPrimaryAttack = gpGlobals->time + 0.1; |
to
| | if(m_usFireMode == MODE_RAPID) { m_flNextPrimaryAttack = gpGlobals->time + 0.05; } else if(m_usFireMode == MODE_AUTO) { m_flNextPrimaryAttack = gpGlobals->time + 0.025; } else { m_flNextPrimaryAttack = gpGlobals->time + 0.1; }
|
This speeds up the firing.
To make the MP5 less accurate, change the VECTOR_CONE_6DEGREES to VECTOR_CONE_15DEGREES in the FireBulletsPlayer function. Save the mp5.cpp file. That’s all for the code. So build the mp.dll
To enable the player to bind the new functions to key you have to create the following directory structure in your mod directory: \gfx\shell Then copy the kb_act.lst file from \valve\gfx\shell to your “shell” directory. Edit the kb_act.lst using notepad or something and add the following lines, anywhere you like:
| | "firemode" "Weapon Fire Mode" "zoommode" "Weapon Zoom Mode" |
That’s all folks. You can e-mail me at scobra@ananzi.co.za for comments and questions. There are better ways to do this but I found that this works. You can change the MODE_SINGLE, MODE_RAPID and MODE_AUTO to values that you use to divide the time with. |
|
User Comments
No User Comments
You must register to post a comment. If you have already registered, you must login.
|
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (6 guests)
|
|