int m_iGotSentryParts; // is 1 when you have the parts. Initialise it to 0 at spawn
int m_iPrevGotSentryParts; // Used to find out if we need to show the sprite on the HUD
Open up player.cpp and initialise these values at CBaseplayer::Spawn()...
m_iPrevGotSentryParts = 0; // Dont set this anywhere else except in UpdateClientData ONCE!
m_iGotSentryParts = 0;
Just as a precaution, go into CBasePlayer::PreThink() and add this...
if( !IsAlive() )
m_iGotSentryParts = 0;
This is so the player loses the sentry parts when the player dies.
class CMySentry_Pickup : public CBaseEntity
{
public:
void Spawn(void);
void Precache(void);
void EXPORT PickupTouch(CBaseEntity *pOther);
};
LINK_ENTITY_TO_CLASS( MySentry_parts, CMySentry_Pickup );
/*Dont forget this, 'MySentry_parts' will be the classname,
you can change this, although they need to match up with the rest of the code. */
Next we'll have the spawn function, where we call precache, initialise variables and set the touch function to PickupTouch()
void CMySentry_Pickup :: Spawn(void)
{
Precache();
SET_MODEL(ENT(pev),"models/w_isotopebox.mdl"); // We'll use the isotope box model at the moment
UTIL_SetSize(pev,Vector(-16,-16,-16),Vector(16,16,16));
UTIL_SetOrigin(pev,pev->origin);
pev->spawnflags &= ~SF_NORESPAWN;
pev->gravity = 1;
pev->solid = SOLID_TRIGGER; // You can walk through it but you can touch it!
pev->health = 100;
pev->max_health = pev->health;
pev->takedamage = DAMAGE_NO;
pev->deadflag = DEAD_NO;
pev->movetype = MOVETYPE_FLY;
pev->sequence = 0;
pev->frame = 0;
pev->nextthink = gpGlobals->time + 0.1;
SetTouch(PickupTouch);
}
The precahce funtion should be simple.. below
void CMySentry_Pickup :: Precache(void)
{
PRECACHE_MODEL("models/w_isotopebox.mdl");
}
The pickupTouch function is called when something touches the box, so we want to check if a player touches it, if so, set the sentry parts to 1 for that player and remove the box.
void CMySentry_Pickup :: PickupTouch (CBaseEntity *pOther)
{
if( pOther->pev->flags & FL_CLIENT )
{
CBasePlayer *pPlayer = GetClassPtr((CBasePlayer*)pOther->pev);
if( pPlayer && !pPlayer->m_iGotSentryParts ) // Check if we can pick it up
{
pPlayer->m_iGotSentryParts = 1;
Killed(pev,GIB_NEVER); // Remove the parts
}
}
}
Save and build, You can now spawn this entity in the map by spawning the classname you specified in the LINK_ENTITY_TO_CLASS call.
else if ( FStrEq(pcmd, "build_sentry" ) )
{
if( m_pPlayer->m_Sentry )
{
ClientPrint( &pEntity->v, HUD_PRINTCENTER, "Sentry Already Built!\n");
}
else
{
if( m_pPlayer->m_iGotSentryParts ) // got the parts?
{
Vector origin = UTIL_ForwardPosition(pEntity,64.0);
origin.z = m_pPlayer->pev->absmin.z + 24;
CBaseEntity *Sentry = CBaseEntity::Create( "MySentry", origin, pev->angles, pEntity );
if( !FNullEnt(Sentry->edict()) )
{
m_pPlayer->m_Sentry = Sentry;
Sentry->pev->owner = pEntity;
ClientPrint( pev, HUD_PRINTCENTER, "Building Sentry...\n");
m_pPlayer->m_iGotSentryParts = 0; // Set parts to zero since we've used them
}
else
ALERT(at_console,"Error allocating new edict for sentry!\n");
}
else
ClientPrint( &pEntity->v, HUD_PRINTCENTER, "You don't have any sentry parts!\n");
}
}
int gmsgSentryParts = 0;
Now go into LinkUserMessages() in player.h and where there are a lot of variables being set to a REG_USER_MSG, add a new one underneath them liek this..
gmsgSentryParts = REG_USER_MSG("SentryParts",1);
Now staying in player.cpp, goto UpdateClientData() and after the HIDE_HUD stuff, add these lines
if ( m_iPrevGotSentryParts != m_iGotSentryParts )
{
int write_byte = 0;
if( m_iGotSentryParts )
write_byte = 1;
MESSAGE_BEGIN( MSG_ONE, gmsgSentryParts, NULL, pev );
WRITE_BYTE( write_byte );
MESSAGE_END();
m_iPrevGotSentryParts = m_iGotSentryParts;
}
That should be all the message stuff figured out, now save all the files and build.
class CHudSentryParts: public CHudBase
{
public:
int Init( void );
int VidInit( void );
int Draw(float flTime);
int MsgFunc_SentryParts(const char *pszName, int iSize, void *pbuf );
private:
HSPRITE m_hSpriteSentryParts1;
};
Go further down the hud.h file now and search for "GetSpriteIndex", below it you'll see a few lines declaring classess as variable structures, below them add the new line
CHudSentryParts m_SentryParts;
That should be all int hud.h, now open up "hud.cpp"... Search for ".Init()" and where you find it, add the new line below it..
m_SentryParts.Init();
Now search for ".VidInit" and add the new line below one of the found lines
m_SentryParts.VidInit();
That is all in hud.cpp. Now we need to make our own file to contain the code for our SentryParts class.
#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
Now declare the SentrtyParts message, this is the same name as the message name ("SentryParts")
DECLARE_MESSAGE(m_SentryParts, SentryParts)
Now declare the name of the sprite here, I've made my own sprite called sentryparts.spr (32x32 pixels), You can call it whatever you want, as long as the file exists so you can see it!
#define SPRITE_NAME "sprites/sentryparts.spr"
Note that the Init() Code below will hook the SentryParts message And make sure the class is called when we send the SentryParts net message
int CHudSentryParts ::Init(void)
{
HOOK_MESSAGE(SentryParts);
gHUD.AddHudElem(this);
return 1;
}
The ViDInit part below will just initialise some variables or whever else you want to do, at the moment I've only got one variable to initialise so it looks very simple.
int CHudSentryParts ::VidInit(void)
{
m_hSpriteSentryParts1 = 0;
return 1;
}
The draw funtion below will be called when the sprite is drawn on the hud.
int CHudSentryParts ::Draw(float flTime)
{
int r,g,b;
if ( !m_hSpriteSentryParts1 )
{
m_hSpriteSentryParts1 = LoadSprite(SPRITE_NAME);
}
if( !m_hSpriteSentryParts1 )
return 0; // Sprite doesn't exist, return 0
UnpackRGB(r, g, b, RGB_YELLOWISH); // "Yellowish" colour
SPR_Set(m_hSpriteSentryParts1, r, g, b); // Set these colours
int x = ScreenWidth - 64; // I've made my sprite 32 pixels wide so I just moved it 64 pixels from the edge of the screen
int y = ScreenHeight - (ScreenHeight/2); // I made it centre vertically.
// X and Y are positions on the HUD.
SPR_DrawAdditive(0, x, y, NULL); // Draw the sprite on X,Y
return 1;
}
The last bit is called when the message "SentryParts" is made, the READ_BYTE() will be the state of the sprite being shown (i.e. if it's 1, draw the sprite on the hud, if not then stop drawing it)
int CHudSentryParts ::MsgFunc_SentryParts(const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
int flag = READ_BYTE();
if (flag == 0)
m_iFlags &= ~HUD_ACTIVE; // turn off the Draw function
else
m_iFlags |= HUD_ACTIVE; // else Draw it!
return 1;
}
You must log in to post a comment. You can login or register a new account.