Refactor some duplicated and bloated code.

This commit is contained in:
Night Owl 2018-04-21 13:20:06 +05:00
parent 193f999cf4
commit 26f710df68
19 changed files with 2148 additions and 2612 deletions

View File

@ -51,160 +51,149 @@ int CHudFlagStatus::Init(void)
HOOK_MESSAGE( RuneStat );
HOOK_MESSAGE( FlagCarrier );
m_iFlags |= HUD_ACTIVE;
m_iFlags |= HUD_ACTIVE;
gHUD.AddHudElem(this);
Reset();
return 1;
};
int CHudFlagStatus::VidInit(void)
return 1;
};
int CHudFlagStatus::VidInit()
{
m_iBlueAtBaseIndex = gHUD.GetSpriteIndex( "blue_atbase" );
m_iBlueLostIndex = gHUD.GetSpriteIndex( "blue_lost" );
m_iBlueStolenIndex = gHUD.GetSpriteIndex( "blue_stolen" );
m_hBlueAtBase = gHUD.GetSprite( gHUD.GetSpriteIndex( "blue_atbase" ) );
m_hBlueLost = gHUD.GetSprite( gHUD.GetSpriteIndex( "blue_lost" ) );
m_hBlueStolen = gHUD.GetSprite( gHUD.GetSpriteIndex( "blue_stolen" ) );
m_iRedAtBaseIndex = gHUD.GetSpriteIndex( "red_atbase" );
m_iRedLostIndex = gHUD.GetSpriteIndex( "red_lost" );
m_iRedStolenIndex = gHUD.GetSpriteIndex( "red_stolen" );
m_hRedAtBase = gHUD.GetSprite( gHUD.GetSpriteIndex( "red_atbase" ) );
m_hRedLost = gHUD.GetSprite( gHUD.GetSpriteIndex( "red_lost" ) );
m_hRedStolen = gHUD.GetSprite( gHUD.GetSpriteIndex( "red_stolen" ) );
m_iRune1Index = gHUD.GetSpriteIndex( "rune1" );
m_iRune2Index = gHUD.GetSpriteIndex( "rune2" );
m_iRune3Index = gHUD.GetSpriteIndex( "rune3" );
m_iRune4Index = gHUD.GetSpriteIndex( "rune4" );
m_hBlueAtBase = gHUD.GetSprite( m_iBlueAtBaseIndex );
m_hBlueLost = gHUD.GetSprite( m_iBlueLostIndex );
m_hBlueStolen = gHUD.GetSprite( m_iBlueStolenIndex );
m_hRedAtBase = gHUD.GetSprite( m_iRedAtBaseIndex );
m_hRedLost = gHUD.GetSprite( m_iRedLostIndex );
m_hRedStolen = gHUD.GetSprite( m_iRedStolenIndex );
m_hRune1 = gHUD.GetSprite( m_iRune1Index );
m_hRune2 = gHUD.GetSprite( m_iRune2Index );
m_hRune3 = gHUD.GetSprite( m_iRune3Index );
m_hRune4 = gHUD.GetSprite( m_iRune4Index );
m_hRune1 = gHUD.GetSprite( gHUD.GetSpriteIndex( "rune1" ) );
m_hRune2 = gHUD.GetSprite( gHUD.GetSpriteIndex( "rune2" ) );
m_hRune3 = gHUD.GetSprite( gHUD.GetSpriteIndex( "rune3" ) );
m_hRune4 = gHUD.GetSprite( gHUD.GetSpriteIndex( "rune4" ) );
// Load sprites here
m_iBlueFlagIndex = gHUD.GetSpriteIndex( "b_flag_c" );
m_iRedFlagIndex = gHUD.GetSpriteIndex( "r_flag_c" );
m_hBlueFlag = gHUD.GetSprite( gHUD.GetSpriteIndex( "b_flag_c" ) );
m_hRedFlag = gHUD.GetSprite( gHUD.GetSpriteIndex( "r_flag_c" ) );
m_hBlueFlag = gHUD.GetSprite( m_iBlueFlagIndex );
m_hRedFlag = gHUD.GetSprite( m_iRedFlagIndex );
return 1;
return 1;
}
void CHudFlagStatus :: Reset( void )
void CHudFlagStatus::Reset()
{
return;
return;
}
int CHudFlagStatus ::Draw(float flTime )
int CHudFlagStatus::Draw( float flTime )
{
HSPRITE hSprite = 0;
int iDigits = DHN_DRAWZERO;
if ( !iDrawStatus )
return 1;
if( !iDrawStatus )
return 1;
int x, y;
int r,g,b;
int x, y;
int r, g, b;
r = g = b = 255;
r = g = b = 255;
x = 20;
y = ( ScreenHeight - gHUD.m_iFontHeight ) - ( gHUD.m_iFontHeight / 2 ) - 40;
x = 20;
y = ( ScreenHeight - gHUD.m_iFontHeight ) - ( gHUD.m_iFontHeight / 2 ) - 40;
switch ( iBlueFlagStatus )
{
case BLUE_FLAG_STOLE:
SPR_Set( m_hBlueStolen, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
break;
case BLUE_FLAG_LOST:
SPR_Set( m_hBlueLost, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
break;
case BLUE_FLAG_ATBASE:
SPR_Set( m_hBlueAtBase, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
break;
}
switch( iBlueFlagStatus )
{
case BLUE_FLAG_STOLE:
hSprite = m_hBlueStolen;
break;
case BLUE_FLAG_LOST:
hSprite = m_hBlueLost;
break;
case BLUE_FLAG_ATBASE:
hSprite = m_hBlueAtBase;
break;
default:
return 1;
}
x = 50;
if ( iBlueTeamScore < 10)
{
x += 3;
gHUD.DrawHudNumber( x, y + 4, DHN_DRAWZERO, iBlueTeamScore, 255, 255, 255 );
}
else if ( iBlueTeamScore >= 10 && iBlueTeamScore < 100 )
gHUD.DrawHudNumber( x, y + 4, DHN_2DIGITS | DHN_DRAWZERO, iBlueTeamScore, 255, 255, 255 );
x = 20;
y = ( ScreenHeight - gHUD.m_iFontHeight ) - ( gHUD.m_iFontHeight / 2 ) - 75;
SPR_Set( hSprite, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
switch ( iRedFlagStatus )
{
case RED_FLAG_STOLE:
SPR_Set( m_hRedStolen, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
break;
case RED_FLAG_LOST:
SPR_Set( m_hRedLost, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
break;
case RED_FLAG_ATBASE:
SPR_Set( m_hRedAtBase, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
break;
}
x = 50;
if( iBlueTeamScore < 10 )
{
x += 3;
}
else if( iBlueTeamScore >= 10 && iBlueTeamScore < 100 )
iDigits |= DHN_2DIGITS;
gHUD.DrawHudNumber( x, y + 4, iDigits, iBlueTeamScore, 255, 255, 255 );
x = 20;
y -= 35;
switch( iRedFlagStatus )
{
case RED_FLAG_STOLE:
hSprite = m_hRedStolen;
break;
case RED_FLAG_LOST:
hSprite = m_hRedLost;
break;
case RED_FLAG_ATBASE:
hSprite = m_hRedAtBase;
break;
default:
return 1;
}
SPR_Set( hSprite, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
x = 50;
if ( iRedTeamScore < 10)
{
x += 3;
gHUD.DrawHudNumber( x, y + 4, DHN_DRAWZERO, iRedTeamScore, 255, 255, 255 );
}
else if ( iBlueTeamScore >= 10 && iBlueTeamScore < 100 )
gHUD.DrawHudNumber( x, y + 4, DHN_2DIGITS | DHN_DRAWZERO, iRedTeamScore, 255, 255, 255 );
x = 50;
iDigits = DHN_DRAWZERO;
x = 20;
y = ( ScreenHeight - gHUD.m_iFontHeight ) - ( gHUD.m_iFontHeight / 2 ) - 110;
if( iRedTeamScore < 10 )
{
x += 3;
}
else if( iRedTeamScore >= 10 && iRedTeamScore < 100 )
iDigits |= DHN_2DIGITS;
switch ( m_iRuneStat )
{
case ITEM_RUNE1_FLAG:
SPR_Set( m_hRune1, r, g, b );
SPR_Draw( 1, x, y, NULL );
break;
gHUD.DrawHudNumber( x, y + 4, iDigits, iRedTeamScore, 255, 255, 255 );
case ITEM_RUNE2_FLAG:
SPR_Set( m_hRune2, r, g, b );
SPR_Draw( 1, x, y, NULL );
break;
x = 20;
y -= 35;
case ITEM_RUNE3_FLAG:
SPR_Set( m_hRune3, r, g, b );
SPR_Draw( 1, x, y, NULL );
break;
switch( m_iRuneStat )
{
case ITEM_RUNE1_FLAG:
hSprite = m_hRune1;
break;
case ITEM_RUNE2_FLAG:
hSprite = m_hRune2;
break;
case ITEM_RUNE3_FLAG:
hSprite = m_hRune3;
break;
case ITEM_RUNE4_FLAG:
hSprite = m_hRune4;
break;
default:
return 1;
}
SPR_Set( hSprite, r, g, b );
SPR_DrawHoles( 1, x, y, NULL );
case ITEM_RUNE4_FLAG:
SPR_Set( m_hRune4, r, g, b );
SPR_Draw( 1, x, y, NULL );
break;
}
return 1;
return 1;
}
int CHudFlagStatus::MsgFunc_FlagStat(const char *pszName, int iSize, void *pbuf)
{
BEGIN_READ( pbuf, iSize );
BEGIN_READ( pbuf, iSize );
iDrawStatus = READ_BYTE();
iRedFlagStatus = READ_BYTE();

View File

@ -99,7 +99,7 @@ set (CLDLL_SOURCES
view.cpp
scoreboard.cpp
MOTD.cpp)
include_directories (. hl/ ../dlls ../dlls/wpn_shared ../common ../engine ../pm_shared ../game_shared ../public dmc ../dlls/dmc ../dlls/dmc .. ../dlls/aghl ../utils/false_vgui/include )
include_directories (. hl/ ../dlls ../dlls/wpn_shared ../common ../engine ../pm_shared ../game_shared ../public dmc ../dlls/dmc ../dlls/dmc .. ../dlls/aghl ../dlls/3wave ../utils/false_vgui/include )
if(USE_VOICEMGR)
#set(CLDLL_SOURCES

View File

@ -602,20 +602,6 @@ public:
HSPRITE m_hRedFlag;
private:
int m_iBlueAtBaseIndex;
int m_iBlueFlagIndex;
int m_iBlueLostIndex;
int m_iBlueStolenIndex;
int m_iRedAtBaseIndex;
int m_iRedFlagIndex;
int m_iRedLostIndex;
int m_iRedStolenIndex;
int m_iRune1Index;
int m_iRune2Index;
int m_iRune3Index;
int m_iRune4Index;
int m_iRuneStat;
HSPRITE m_hBlueAtBase;

570
dlls/3wave/flags.cpp Normal file
View File

@ -0,0 +1,570 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
/*****************************************************
******************************************************
THREEWAVE CTF FLAG CODE
******************************************************
*****************************************************/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "items.h"
#include "threewave_gamerules.h"
#include "flags.h"
unsigned short g_usCarried;
unsigned short g_usFlagSpawn;
enum Flag_Anims
{
ON_GROUND = 0,
NOT_CARRIED,
CARRIED,
WAVE_IDLE,
FLAG_POSITION
};
void CItemFlag::Spawn()
{
Precache();
SET_MODEL( ENT( pev ), "models/flag.mdl" );
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_TRIGGER;
UTIL_SetOrigin( pev, pev->origin );
UTIL_SetSize( pev, Vector( -16, -16, 0 ), Vector( 16, 16, 16 ) );
SetThink( &CItemFlag::FlagThink );
SetTouch( &CItemFlag::FlagTouch );
pev->nextthink = gpGlobals->time + 0.3;
//Set the Skin based on the team.
pev->skin = pev->team;
Dropped = FALSE;
m_flDroppedTime = 0.0;
pev->sequence = NOT_CARRIED;
pev->framerate = 1.0;
// if( !DROP_TO_FLOOR( ENT( pev ) ) )
// ResetFlag( pev->team );
}
void CItemFlag::FlagTouch( CBaseEntity *pToucher )
{
if( !pToucher )
return;
if( !pToucher->IsPlayer() )
return;
if( FBitSet( pev->effects, EF_NODRAW ) )
return;
if( pToucher->pev->health <= 0 )
return;
if( pToucher->pev->team == 0 )
return;
CBasePlayer *pPlayer = (CBasePlayer *)pToucher;
//Same team as the flag
if( pev->team == pToucher->pev->team )
{
//Flag is dropped, let's return it
if( Dropped )
{
Dropped = FALSE;
pPlayer->AddPoints( TEAM_CAPTURE_RECOVERY_BONUS, TRUE );
if( pPlayer->pev->team == RED )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Returned_Red_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
if( ( (CThreeWave*)g_pGameRules )->iBlueFlagStatus == BLUE_FLAG_STOLEN )
{
for( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer *pTeamMate = (CBasePlayer*)UTIL_PlayerByIndex( i );
if( pTeamMate )
{
if( pTeamMate->m_bHasFlag )
{
pTeamMate->pFlagReturner = pPlayer;
pTeamMate->m_flFlagReturnTime = gpGlobals->time + TEAM_CAPTURE_RETURN_FLAG_ASSIST_TIMEOUT;
}
}
}
}
}
if( pPlayer->pev->team == BLUE )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Returned_Blue_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
if( ( (CThreeWave*)g_pGameRules )->iRedFlagStatus == RED_FLAG_STOLEN )
{
for( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer *pTeamMate = (CBasePlayer*)UTIL_PlayerByIndex( i );
if( pTeamMate )
{
if( pTeamMate->m_bHasFlag )
{
pTeamMate->pFlagReturner = pPlayer;
pTeamMate->m_flFlagReturnTime = gpGlobals->time + TEAM_CAPTURE_RETURN_FLAG_ASSIST_TIMEOUT;
}
}
}
}
}
//Back at home!
ResetFlag( pev->team );
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL );
if( pev->team == RED )
WRITE_BYTE( RED_FLAG_RETURNED_PLAYER );
else if( pev->team == BLUE )
WRITE_BYTE( BLUE_FLAG_RETURNED_PLAYER );
WRITE_STRING( STRING( pToucher->pev->netname ) );
MESSAGE_END();
// Remove this one
UTIL_Remove( this );
return;
}
// Not Dropped, means it's the one in our base
else
{
// We have the enemy flag!
// Capture it!
if( pPlayer->m_bHasFlag )
{
if( pev->team == RED )
Capture( pPlayer, BLUE );
else if( pev->team == BLUE )
Capture( pPlayer, RED );
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
pPlayer->edict(), g_usCarried, 0, (float*)&g_vecZero, (float*)&g_vecZero,
0.0, 0.0, pPlayer->entindex(), pPlayer->pev->team, 1, 0 );
return;
}
}
}
else
{
if( Dropped )
{
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL );
if( pev->team == RED )
WRITE_BYTE( RED_FLAG_STOLEN );
else if( pev->team == BLUE )
WRITE_BYTE( BLUE_FLAG_STOLEN );
WRITE_STRING( STRING( pToucher->pev->netname ) );
MESSAGE_END();
pPlayer->m_bHasFlag = TRUE;
CBaseEntity *pEnt = NULL;
if( pev->team == RED )
{
pEnt = CBaseEntity::Create( "carried_flag_team1", pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Picked_Up_Red_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
}
else if( pev->team == BLUE )
{
pEnt = CBaseEntity::Create( "carried_flag_team2", pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Picked_Up_Blue_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
}
CCarriedFlag *pCarriedFlag = (CCarriedFlag *)pEnt;
pCarriedFlag->Owner = pPlayer;
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
pPlayer->edict(), g_usCarried, 0, (float*)&g_vecZero, (float*)&g_vecZero,
0.0, 0.0, pPlayer->entindex(), pPlayer->pev->team, 0, 0 );
UTIL_Remove( this );
}
else
{
pev->effects |= EF_NODRAW;
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL );
if( pev->team == RED )
WRITE_BYTE( RED_FLAG_STOLEN );
else if( pev->team == BLUE )
WRITE_BYTE( BLUE_FLAG_STOLEN );
WRITE_STRING( STRING( pToucher->pev->netname ) );
MESSAGE_END();
pPlayer->m_bHasFlag = TRUE;
pPlayer->m_flCarrierPickupTime = gpGlobals->time + TEAM_CAPTURE_CARRIER_FLAG_SINCE_TIMEOUT;
CBaseEntity *pEnt = NULL;
if( pev->team == RED )
{
pEnt = CBaseEntity::Create( "carried_flag_team1", pev->origin, pev->angles, pPlayer->edict() );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Stole_Red_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
}
else if( pev->team == BLUE )
{
pEnt = CBaseEntity::Create( "carried_flag_team2", pev->origin, pev->angles, pPlayer->edict() );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Stole_Blue_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
}
CCarriedFlag *pCarriedFlag = (CCarriedFlag *)pEnt;
pCarriedFlag->Owner = pPlayer;
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
pPlayer->edict(), g_usCarried, 0, (float*)&g_vecZero, (float*)&g_vecZero,
0.0, 0.0, pPlayer->entindex(), pPlayer->pev->team, 0, 0 );
}
( (CThreeWave*)g_pGameRules )->m_flFlagStatusTime = gpGlobals->time + 0.1;
}
}
void CItemFlag::Capture( CBasePlayer *pPlayer, int iTeam )
{
CBaseEntity *pFlag1 = NULL;
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL );
if( iTeam == RED )
WRITE_BYTE( RED_FLAG_CAPTURED );
else if ( iTeam == BLUE )
WRITE_BYTE( BLUE_FLAG_CAPTURED );
WRITE_STRING( STRING( pPlayer->pev->netname ) );
MESSAGE_END();
if( pPlayer->pFlagCarrierKiller )
{
if( pPlayer->m_flFlagCarrierKillTime > gpGlobals->time )
{
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pPlayer->pFlagCarrierKiller->pev->netname ) );
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " gets an assist for fragging the flag carrier!\n" );
pPlayer->pFlagCarrierKiller->AddPoints( TEAM_CAPTURE_FRAG_CARRIER_ASSIST_BONUS, TRUE );
pPlayer->pFlagCarrierKiller = NULL;
pPlayer->m_flFlagCarrierKillTime = 0.0;
}
}
if( pPlayer->pFlagReturner )
{
if( pPlayer->m_flFlagReturnTime > gpGlobals->time )
{
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pPlayer->pFlagReturner->pev->netname ) );
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " gets an assist for returning his flag!\n");
pPlayer->pFlagReturner->AddPoints( TEAM_CAPTURE_RETURN_FLAG_ASSIST_BONUS, TRUE );
pPlayer->pFlagReturner = NULL;
pPlayer->m_flFlagReturnTime = 0.0;
}
}
if( iTeam != pPlayer->pev->team )
{
if( iTeam == RED )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Captured_Red_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
}
else
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Captured_Blue_Flag\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
GetTeamName( pPlayer->pev->team ) );
}
}
if( iTeam == RED )
{
( (CThreeWave *)g_pGameRules )->iBlueTeamScore++;
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "carried_flag_team1" ) ) != NULL )
{
if( pFlag1 )
UTIL_Remove( pFlag1 );
}
}
else if( iTeam == BLUE )
{
( (CThreeWave*)g_pGameRules )->iRedTeamScore++;
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "carried_flag_team2" ) ) != NULL )
{
if ( pFlag1 )
UTIL_Remove( pFlag1 );
}
}
pPlayer->m_bHasFlag = FALSE;
pPlayer->AddPoints( TEAM_CAPTURE_CAPTURE_BONUS, TRUE );
for( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *pTeamMate = UTIL_PlayerByIndex( i );
if( pTeamMate )
{
if( pTeamMate->pev->team == pPlayer->pev->team )
pTeamMate->AddPoints( TEAM_CAPTURE_TEAM_BONUS, TRUE );
}
}
ResetFlag( iTeam );
}
void CItemFlag::Materialize()
{
if ( pev->effects & EF_NODRAW )
{
pev->effects &= ~EF_NODRAW;
pev->effects |= EF_MUZZLEFLASH;
}
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
edict(), g_usFlagSpawn, 0, (float*)&g_vecZero, (float*)&g_vecZero,
0.0, 0.0, pev->team, 0, 0, 0 );
Dropped = FALSE;
SetTouch( &CItemFlag::FlagTouch );
SetThink( &CItemFlag::FlagThink );
}
void CItemFlag::ResetFlag( int iTeam )
{
CBaseEntity *pFlag1 = NULL;
if( iTeam == BLUE )
{
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "item_flag_team2" ) ) != NULL )
{
CItemFlag *pFlag2 = (CItemFlag*)pFlag1;
if( pFlag2->Dropped )
continue;
if( pFlag2->pev->effects & EF_NODRAW )
pFlag2->Materialize();
}
}
else if( iTeam == RED )
{
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "item_flag_team1" ) ) != NULL )
{
CItemFlag *pFlag2 = (CItemFlag*)pFlag1;
if( pFlag2->Dropped )
continue;
if( pFlag2->pev->effects & EF_NODRAW )
pFlag2->Materialize();
}
}
( (CThreeWave*)g_pGameRules )->m_flFlagStatusTime = gpGlobals->time + 0.1;
}
void CItemFlag::FlagThink()
{
if( Dropped )
{
if( m_flDroppedTime <= gpGlobals->time )
{
ResetFlag( pev->team );
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL );
if( pev->team == RED )
WRITE_BYTE( RED_FLAG_RETURNED );
else if( pev->team == BLUE )
WRITE_BYTE( BLUE_FLAG_RETURNED );
WRITE_STRING( "" );
MESSAGE_END();
UTIL_Remove( this );
return;
}
}
//Using 0.2 just in case we might lag the server.
pev->nextthink = gpGlobals->time + 0.2;
}
void CItemFlag::Precache()
{
PRECACHE_MODEL( "models/flag.mdl" );
PRECACHE_SOUND( "ctf/flagcap.wav" );
PRECACHE_SOUND( "ctf/flagtk.wav" );
PRECACHE_SOUND( "ctf/flagret.wav" );
}
class CItemFlagTeam1 : public CItemFlag
{
void Spawn()
{
pev->classname = MAKE_STRING( "item_flag_team1" );
pev->team = RED;
CItemFlag::Spawn();
}
};
class CItemFlagTeam2 : public CItemFlag
{
void Spawn()
{
pev->classname = MAKE_STRING( "item_flag_team2" );
pev->team = BLUE;
CItemFlag::Spawn();
}
};
LINK_ENTITY_TO_CLASS( item_flag_team1, CItemFlagTeam1 )
LINK_ENTITY_TO_CLASS( ctf_redflag, CItemFlagTeam1 )
LINK_ENTITY_TO_CLASS( item_flag_team2, CItemFlagTeam2 )
LINK_ENTITY_TO_CLASS( ctf_blueflag, CItemFlagTeam2 )
void CCarriedFlag::Spawn()
{
Precache();
SET_MODEL( ENT( pev ), "models/flag.mdl" );
UTIL_SetOrigin( pev, pev->origin );
pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_NOT;
pev->effects |= EF_NODRAW;
pev->sequence = WAVE_IDLE;
pev->framerate = 1.0;
/*
if( pev->team == RED )
pev->skin = 1;
else if( pev->team == BLUE )
pev->skin = 2;*/
pev->skin = pev->team;
m_iOwnerOldVel = 0;
SetThink( &CCarriedFlag::FlagThink );
pev->nextthink = gpGlobals->time + 0.1;
}
void CCarriedFlag::Precache()
{
PRECACHE_MODEL( "models/flag.mdl" );
}
void CCarriedFlag::FlagThink()
{
// Make it visible
pev->effects &= ~EF_NODRAW;
// And let if follow
pev->aiment = ENT( Owner->pev );
pev->movetype = MOVETYPE_FOLLOW;
// If owner is death or lost flag, remove
if( !Owner->IsAlive() || !Owner->m_bHasFlag )
UTIL_Remove( this );
else
{
// If owners speed is low, go in idle mode
if( Owner->pev->velocity.Length() <= 75 && pev->sequence != WAVE_IDLE )
{
pev->sequence = WAVE_IDLE;
}
// Else let the flag go wild
else if( Owner->pev->velocity.Length() >= 75 && pev->sequence != CARRIED )
{
pev->sequence = CARRIED;
}
pev->frame += pev->framerate;
if( pev->frame < 0.0 || pev->frame >= 256.0 )
{
pev->frame -= (int)( pev->frame / 256.0 ) * 256.0;
}
pev->nextthink = gpGlobals->time + 0.1;
}
}
class CCarriedFlagTeam1 : public CCarriedFlag
{
void Spawn()
{
pev->team = RED;
CCarriedFlag::Spawn();
}
};
class CCarriedFlagTeam2 : public CCarriedFlag
{
void Spawn()
{
pev->team = BLUE;
CCarriedFlag::Spawn();
}
};
LINK_ENTITY_TO_CLASS( carried_flag_team1, CCarriedFlagTeam1 )
LINK_ENTITY_TO_CLASS( carried_flag_team2, CCarriedFlagTeam2 )

107
dlls/3wave/flags.h Normal file
View File

@ -0,0 +1,107 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//=========================================================
// Flags
//=========================================================
#pragma once
#ifndef FLAGS_H
#define FLAGS_H
#define STEAL_SOUND 1
#define CAPTURE_SOUND 2
#define RETURN_SOUND 3
#define RED_FLAG_STOLEN 1
#define BLUE_FLAG_STOLEN 2
#define RED_FLAG_CAPTURED 3
#define BLUE_FLAG_CAPTURED 4
#define RED_FLAG_RETURNED_PLAYER 5
#define BLUE_FLAG_RETURNED_PLAYER 6
#define RED_FLAG_RETURNED 7
#define BLUE_FLAG_RETURNED 8
#define RED_FLAG_LOST 9
#define BLUE_FLAG_LOST 10
#define RED_FLAG_STOLEN 1
#define BLUE_FLAG_STOLEN 2
#define RED_FLAG_DROPPED 3
#define BLUE_FLAG_DROPPED 4
#define RED_FLAG_ATBASE 5
#define BLUE_FLAG_ATBASE 6
// Standard Scoring
#define TEAM_CAPTURE_CAPTURE_BONUS 5 // what you get for capture
#define TEAM_CAPTURE_TEAM_BONUS 10 // what your team gets for capture
#define TEAM_CAPTURE_RECOVERY_BONUS 1 // what you get for recovery
#define TEAM_CAPTURE_FLAG_BONUS 0 // what you get for picking up enemy flag
#define TEAM_CAPTURE_FRAG_CARRIER_BONUS 2 // what you get for fragging a enemy flag carrier
#define TEAM_CAPTURE_FLAG_RETURN_TIME 40 // seconds until auto return
// bonuses
#define TEAM_CAPTURE_CARRIER_DANGER_PROTECT_BONUS 2 // bonus for fraggin someone
// who has recently hurt your flag carrier
#define TEAM_CAPTURE_CARRIER_PROTECT_BONUS 1 // bonus for fraggin someone while
// either you or your target are near your flag carrier
#define TEAM_CAPTURE_FLAG_DEFENSE_BONUS 1 // bonus for fraggin someone while
// either you or your target are near your flag
#define TEAM_CAPTURE_RETURN_FLAG_ASSIST_BONUS 1 // awarded for returning a flag that causes a
// capture to happen almost immediately
#define TEAM_CAPTURE_FRAG_CARRIER_ASSIST_BONUS 2 // award for fragging a flag carrier if a
// capture happens almost immediately
// Radius
#define TEAM_CAPTURE_TARGET_PROTECT_RADIUS 550 // the radius around an object being
// defended where a target will be worth extra frags
#define TEAM_CAPTURE_ATTACKER_PROTECT_RADIUS 550 // the radius around an object being
// defended where an attacker will get extra frags when making kills
// timeouts
#define TEAM_CAPTURE_CARRIER_DANGER_PROTECT_TIMEOUT 4
#define TEAM_CAPTURE_CARRIER_FLAG_SINCE_TIMEOUT 2
#define TEAM_CAPTURE_FRAG_CARRIER_ASSIST_TIMEOUT 6
#define TEAM_CAPTURE_RETURN_FLAG_ASSIST_TIMEOUT 4
extern const char *GetTeamName( int team );
class CItemFlag : public CBaseEntity
{
public:
void Spawn();
BOOL Dropped;
float m_flDroppedTime;
void EXPORT FlagThink();
private:
void Precache();
void Capture( CBasePlayer *pPlayer, int iTeam );
void ResetFlag( int iTeam );
void Materialize();
void EXPORT FlagTouch( CBaseEntity *pOther );
// BOOL MyTouch( CBasePlayer *pPlayer );
};
class CCarriedFlag : public CBaseEntity
{
public:
void Spawn();
CBasePlayer *Owner;
int m_iOwnerOldVel;
private:
void Precache();
void EXPORT FlagThink();
};
#endif // FLAGS_H

351
dlls/3wave/grapple.cpp Normal file
View File

@ -0,0 +1,351 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
/***********************************************
************************************************
GRAPPLE
************************************************
***********************************************/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "grapple.h"
unsigned short g_usHook;
unsigned short g_usCable;
void CGrapple::Reset_Grapple()
{
CBasePlayer *pOwner = (CBasePlayer *)CBaseEntity::Instance( pev->owner );
pOwner->m_bOn_Hook = FALSE;
pOwner->m_bHook_Out = FALSE;
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
pOwner->edict(), g_usCable, 0, (float*)&g_vecZero, (float*)&g_vecZero,
0.0, 0.0, entindex(), pev->team, 1, 0 );
STOP_SOUND( edict(), CHAN_WEAPON, "weapons/grhang.wav" );
STOP_SOUND( pOwner->edict(), CHAN_WEAPON, "weapons/grfire.wav" );
STOP_SOUND( pOwner->edict(), CHAN_WEAPON, "weapons/grpull.wav" );
pOwner->m_ppHook = NULL;
pev->enemy = NULL;
UTIL_Remove( this );
}
void CGrapple::GrappleTouch( CBaseEntity *pOther )
{
CBasePlayer *pOwner = (CBasePlayer *)CBaseEntity::Instance( pev->owner );
if( pOther == pOwner )
return;
// DO NOT allow the grapple to hook to any projectiles, no matter WHAT!
// if you create new types of projectiles, make sure you use one of the
// classnames below or write code to exclude your new classname so
// grapples will not stick to them.
if( pOther->Classify() == CLASS_PROJECTILE )
return;
if( pOther->IsPlayer() )
{
// glance off of teammates
if( pOther->pev->team == pOwner->pev->team )
return;
// sound( self, CHAN_WEAPON, "player/axhit1.wav", 1, ATTN_NORM );
// TakeDamage( pOther->pev, pOwner->pev, 10, DMG_GENERIC );
// make hook invisible since we will be pulling directly
// towards the player the hook hit. Quakeworld makes it
// too quirky to try to match hook's velocity with that of
// the client that it hit.
// setmodel( self, "");
pev->velocity = g_vecZero;
UTIL_SetOrigin( pev, pOther->pev->origin );
}
else
{
// sound( self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM );
// One point of damage inflicted upon impact. Subsequent
// damage will only be done to PLAYERS... this way secret
// doors and triggers will only be damaged once.
if( pOther->pev->takedamage )
TakeDamage( pOther->pev, pOwner->pev, 1, DMG_GENERIC );
pev->velocity = g_vecZero;
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/grhit.wav", 1, ATTN_NORM );
// No sparks underwater
if( pev->waterlevel == 0 )
UTIL_Sparks( pev->origin );
}
// conveniently clears the sound channel of the CHAIN1 sound,
// which is a looping sample and would continue to play. Tink1 is
// the least offensive choice, ass NULL.WAV loops and clogs the
// channel with silence
// sound (self.owner, CHAN_NO_PHS_ADD+CHAN_WEAPON, "weapons/tink1.wav", 1, ATTN_NORM);
if( !( pOwner->pev->button & IN_ATTACK ) )
{
if( pOwner->m_bOn_Hook )
{
Reset_Grapple();
return;
}
}
if( pOwner->pev->flags & FL_ONGROUND )
{
pOwner->pev->flags &= ~FL_ONGROUND;
// setorigin(self.owner,self.owner.origin + '0 0 1');
}
pOwner->m_bOn_Hook = TRUE;
// sound( self.owner, CHAN_WEAPON, "weapons/chain2.wav", 1, ATTN_NORM );
// CHAIN2 is a looping sample. Use LEFTY as a flag so that client.qc
// will know to only play the tink sound ONCE to clear the weapons
// sound channel. (Lefty is a leftover from AI.QC, so I reused it to
// avoid adding a field)
//self.owner.lefty = TRUE;
STOP_SOUND( pOwner->edict(), CHAN_WEAPON, "weapons/grfire.wav" );
pev->enemy = pOther->edict();// remember this guy!
SetThink( &CGrapple::Grapple_Track );
pev->nextthink = gpGlobals->time;
m_flNextIdleTime = gpGlobals->time + 0.1;
pev->solid = SOLID_NOT;
SetTouch( NULL );
}
bool CanSee( CBaseEntity *pEnemy, CBaseEntity *pOwner )
{
TraceResult tr;
UTIL_TraceLine( pOwner->pev->origin, pEnemy->pev->origin, ignore_monsters, ENT( pOwner->pev ), &tr );
if( tr.flFraction == 1 )
return TRUE;
UTIL_TraceLine( pOwner->pev->origin, pEnemy->pev->origin + Vector( 15, 15, 0 ), ignore_monsters, ENT( pOwner->pev ), &tr );
if( tr.flFraction == 1 )
return TRUE;
UTIL_TraceLine( pOwner->pev->origin, pEnemy->pev->origin + Vector( -15, -15, 0 ), ignore_monsters, ENT( pOwner->pev ), &tr );
if( tr.flFraction == 1 )
return TRUE;
UTIL_TraceLine( pOwner->pev->origin, pEnemy->pev->origin + Vector( -15, 15, 0 ), ignore_monsters, ENT( pOwner->pev ), &tr );
if( tr.flFraction == 1 )
return TRUE;
UTIL_TraceLine( pOwner->pev->origin, pEnemy->pev->origin + Vector( 15, -15, 0 ), ignore_monsters, ENT( pOwner->pev ), &tr );
if( tr.flFraction == 1 )
return TRUE;
return FALSE;
}
void CGrapple::Grapple_Track()
{
CBasePlayer *pOwner = (CBasePlayer*)CBaseEntity::Instance( pev->owner );
CBaseEntity *pEnemy = CBaseEntity::Instance( pev->enemy );
// Release dead targets
if( pEnemy->IsPlayer() && pEnemy->pev->health <= 0 )
Reset_Grapple();
// drop the hook if owner is dead or has released the button
if( !pOwner->m_bOn_Hook || pOwner->pev->health <= 0 )
{
Reset_Grapple();
return;
}
if( !( pOwner->pev->button & IN_ATTACK ) )
{
if( pOwner->m_iQuakeWeapon == IT_EXTRA_WEAPON )
{
Reset_Grapple();
return;
}
}
// bring the pAiN!
if( pEnemy->IsPlayer() )
{
if( !CanSee( pEnemy, pOwner ) )
{
Reset_Grapple();
return;
}
// move the hook along with the player. It's invisible, but
// we need this to make the sound come from the right spot
UTIL_SetOrigin( pev, pEnemy->pev->origin );
// sound( self, CHAN_WEAPON, "blob/land1.wav", 1, ATTN_NORM );
SpawnBlood( pEnemy->pev->origin, BLOOD_COLOR_RED, 1 );
( (CBasePlayer *)pEnemy )->TakeDamage( pev, pOwner->pev, 1, DMG_GENERIC );
}
// If the hook is not attached to the player, constantly copy
// copy the target's velocity. Velocity copying DOES NOT work properly
// for a hooked client.
else
pev->velocity = pEnemy->pev->velocity;
pev->nextthink = gpGlobals->time + 0.1;
}
void CBasePlayer::Service_Grapple()
{
Vector hook_dir;
CBaseEntity *pEnemy = CBaseEntity::Instance( pev->enemy );
// drop the hook if player lets go of button
if( !( pev->button & IN_ATTACK ) )
{
if( m_iQuakeWeapon == IT_EXTRA_WEAPON )
{
m_ppHook->Reset_Grapple();
return;
}
}
if( m_ppHook->pev->enemy != NULL )
{
// If hooked to a player, track them directly!
if( pEnemy->IsPlayer() )
{
pEnemy = CBaseEntity::Instance( pev->enemy );
hook_dir = ( pEnemy->pev->origin - pev->origin );
}
// else, track to hook
else
hook_dir = ( m_ppHook->pev->origin - pev->origin );
pev->speed = 750;
pev->velocity = ( hook_dir.Normalize() * pev->speed );
if( m_ppHook->m_flNextIdleTime <= gpGlobals->time && hook_dir.Length() <= 50 )
{
//No sparks underwater
if( m_ppHook->pev->waterlevel == 0 )
UTIL_Sparks( m_ppHook->pev->origin );
STOP_SOUND( edict(), CHAN_WEAPON, "weapons/grpull.wav" );
EMIT_SOUND( ENT( m_ppHook->pev ), CHAN_WEAPON, "weapons/grhang.wav", 1, ATTN_NORM );
m_ppHook->m_flNextIdleTime = gpGlobals->time + RANDOM_LONG( 1, 3 );
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
edict(), g_usCable, 0, (float *)&g_vecZero, (float *)&g_vecZero,
0.0, 0.0, m_ppHook->entindex(), pev->team, 1, 0 );
}
else if( m_ppHook->m_flNextIdleTime <= gpGlobals->time )
{
// No sparks underwater
if( m_ppHook->pev->waterlevel == 0 )
UTIL_Sparks( m_ppHook->pev->origin );
STOP_SOUND( edict(), CHAN_WEAPON, "weapons/grfire.wav" );
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/grpull.wav", 1, ATTN_NORM );
m_ppHook->m_flNextIdleTime = gpGlobals->time + RANDOM_LONG( 1, 3 );
}
}
}
void CGrapple::OnAirThink()
{
TraceResult tr;
CBaseEntity *pOwner = CBaseEntity::Instance( pev->owner );
if( !( pOwner->pev->button & IN_ATTACK ) )
{
Reset_Grapple();
return;
}
UTIL_TraceLine( pev->origin, pOwner->pev->origin, ignore_monsters, ENT( pev ), &tr );
if( tr.flFraction < 1.0 )
{
Reset_Grapple();
return;
}
pev->nextthink = gpGlobals->time + 0.5;
}
void CGrapple::Spawn()
{
pev->movetype = MOVETYPE_FLYMISSILE;
pev->solid = SOLID_BBOX;
SET_MODEL( ENT( pev ),"models/hook.mdl" );
SetTouch( &CGrapple::GrappleTouch );
SetThink( &CGrapple::OnAirThink );
pev->nextthink = gpGlobals->time + 0.1;
}
LINK_ENTITY_TO_CLASS( hook, CGrapple );
void CBasePlayer::Throw_Grapple()
{
if( m_bHook_Out )
return;
CGrapple *pHookCBEnt = NULL;
pHookCBEnt = (CGrapple*)CBaseEntity::Create( "hook", pev->origin, pev->angles, NULL );
if( pHookCBEnt )
{
m_ppHook = pHookCBEnt;
m_ppHook->pev->owner = edict();
UTIL_MakeVectors( pev->v_angle );
UTIL_SetOrigin( m_ppHook->pev, pev->origin + gpGlobals->v_forward * 16 + Vector( 0, 0, 16 ) );
UTIL_SetSize( m_ppHook->pev, g_vecZero, g_vecZero );
EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "weapons/grfire.wav", 1, ATTN_NORM );
// Make if fly forward
m_ppHook->pev->velocity = gpGlobals->v_forward * 1000;
// And make the hook face forward too!
m_ppHook->pev->angles = UTIL_VecToAngles( gpGlobals->v_forward );
m_ppHook->pev->fixangle = TRUE;
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE,
edict(), g_usCable, 0, (float*)&g_vecZero, (float*)&g_vecZero,
0.0, 0.0, m_ppHook->entindex(), pev->team, 0, 0 );
m_bHook_Out = TRUE;
}
}

32
dlls/3wave/grapple.h Normal file
View File

@ -0,0 +1,32 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#pragma once
#ifndef GRAPPLE_H
#define GRAPPLE_H
class CGrapple : public CBaseEntity
{
public:
//Yes, I have no imagination so I use standard touch, spawn and think function names.
//Sue me! =P.
void Spawn();
int Classify() { return CLASS_PROJECTILE; };
void EXPORT OnAirThink();
void EXPORT GrappleTouch( CBaseEntity *pOther );
void Reset_Grapple();
void EXPORT Grapple_Track();
float m_flNextIdleTime;
};
#endif // GRAPPLE_H

420
dlls/3wave/runes.cpp Normal file
View File

@ -0,0 +1,420 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
/*
***************************************
****************************************
RUNES
****************************************
***************************************/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "threewave_gamerules.h"
#include "runes.h"
extern bool g_bSpawnedRunes;
/*----------------------------------------------------------------------
The Rune Game modes
Rune 1 - Earth Magic
resistance
Rune 2 - Black Magic
strength
Rune 3 - Hell Magic
haste
Rune 4 - Elder Magic
regeneration
----------------------------------------------------------------------*/
BOOL IsRuneSpawnPointValid( CBaseEntity *pSpot )
{
CBaseEntity *ent = NULL;
while( ( ent = UTIL_FindEntityInSphere( ent, pSpot->pev->origin, 128 ) ) != NULL )
{
//Try not to spawn it near other runes.
if( ent->Classify() == CLASS_RUNE )
return FALSE;
}
return TRUE;
}
edict_t *RuneSelectSpawnPoint()
{
CBaseEntity *pSpot = NULL;
// Randomize the start spot
for( int i = RANDOM_LONG( 1, 5 ); i > 0; i-- )
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
if( !pSpot ) // skip over the null point
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
CBaseEntity *pFirstSpot = pSpot;
do
{
if( pSpot )
{
if( IsRuneSpawnPointValid( pSpot ) )
{
if( pSpot->pev->origin == g_vecZero )
{
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
continue;
}
// if so, go to pSpot
goto ReturnSpot;
}
}
// increment pSpot
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
} while ( pSpot != pFirstSpot ); // loop if we're not back to the start
// we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there
if( pSpot )
goto ReturnSpot;
// If startspot is set, (re)spawn there.
if( FStringNull( gpGlobals->startspot ) || !strlen( STRING( gpGlobals->startspot ) ) )
{
pSpot = UTIL_FindEntityByClassname( NULL, "info_player_start" );
}
else
{
pSpot = UTIL_FindEntityByTargetname( NULL, STRING( gpGlobals->startspot ) );
}
ReturnSpot:
if( !pSpot )
{
ALERT( at_error, "PutClientInServer: no info_player_start on level" );
return INDEXENT( 0 );
}
return pSpot->edict();
}
void VectorScale( const float *in, float scale, float *out )
{
out[0] = in[0] * scale;
out[1] = in[1] * scale;
out[2] = in[2] * scale;
}
void G_ProjectSource( vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result )
{
result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1];
result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1];
result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
}
#define VectorSet(v, x, y, z) (v[0]=(x), v[1]=(y), v[2]=(z))
void DropRune( CBasePlayer *pPlayer )
{
TraceResult tr;
// do they even have a rune?
if( pPlayer->m_iRuneStatus == 0 )
return;
// Make Sure there's enough room to drop the rune here
// This is so hacky ( the reason why we are doing this), and I hate it to death.
UTIL_MakeVectors( pPlayer->pev->v_angle );
Vector vecSrc = pPlayer->GetGunPosition( );
Vector vecEnd = vecSrc + gpGlobals->v_forward * 32;
UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, human_hull, ENT( pPlayer->pev ), &tr );
if( tr.flFraction != 1 )
{
ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "Not enough room to drop the rune here." );
return;
}
if( pPlayer->m_iRuneStatus )
{
CItemRune *pRune = (CItemRune*)CBaseEntity::Create( g_RuneEntityName[pPlayer->m_iRuneStatus], pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() );
if( pRune )
pRune->dropped = true;
if( pPlayer->m_iRuneStatus == ITEM_RUNE3_FLAG )
g_engfuncs.pfnSetClientMaxspeed( ENT( pPlayer->pev ), PLAYER_MAX_SPEED ); // Reset Haste player speed to normal
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_%s\"\n",
STRING(pPlayer->pev->netname),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
pPlayer->m_szTeamName,
g_RuneName[pPlayer->m_iRuneStatus] );
pPlayer->m_iRuneStatus = 0;
}
MESSAGE_BEGIN( MSG_ONE, gmsgRuneStatus, NULL, pPlayer->pev );
WRITE_BYTE( pPlayer->m_iRuneStatus );
MESSAGE_END();
}
void CItemRune::Spawn()
{
m_bTouchable = FALSE;
dropped = false;
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_TRIGGER;
vec3_t forward, right, up;
Vector vecAngles;
UTIL_SetSize( pev, Vector( -15, -15, -15 ), Vector( 15, 15, 15 ) );
pev->angles.z = pev->angles.x = 0;
pev->angles.y = RANDOM_LONG ( 0, 360 );
//If we got an owner, it means we are either dropping the flag or diying and letting it go.
if( pev->owner )
vecAngles = pev->owner->v.angles;
else
vecAngles = pev->angles;
g_engfuncs.pfnAngleVectors( vecAngles, forward, right, up );
UTIL_SetOrigin( pev, pev->origin );
pev->velocity = ( forward * 400 ) + ( up * 200 );
if( pev->owner == NULL )
{
pev->origin.z += 16;
pev->velocity.z = 300;
}
pev->owner = NULL;
SetTouch( &CItemRune::RuneTouch );
pev->nextthink = gpGlobals->time + 1; // if no one touches it in two minutes,
// respawn it somewhere else, so inaccessible
// ones will come 'back'
SetThink( &CItemRune::MakeTouchable );
}
void CItemRune::MakeTouchable()
{
m_bTouchable = TRUE;
pev->nextthink = gpGlobals->time + 120; // if no one touches it in two minutes,
// respawn it somewhere else, so inaccessible
// ones will come 'back'
SetThink( &CItemRune::RuneRespawn );
}
void CItemRune::RuneTouch( CBaseEntity *pOther )
{
// No toucher?
if( !pOther )
return;
// Not a player?
if( !pOther->IsPlayer() )
return;
// DEAD?!
if( pOther->pev->health <= 0 )
return;
// Spectating?
if( pOther->pev->movetype == MOVETYPE_NOCLIP )
return;
CBasePlayer *pPlayer = (CBasePlayer*)pOther;
// Only one per customer
if( pPlayer->m_iRuneStatus )
{
ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "You already have a rune!\n" );
return;
}
if( !m_bTouchable )
return;
pPlayer->m_iRuneStatus = m_iRuneFlag; //Add me the rune flag
PrintTouchMessage( pPlayer );
EMIT_SOUND( ENT( pev ), CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM );
//Update my client side rune hud thingy.
MESSAGE_BEGIN( MSG_ONE, gmsgRuneStatus, NULL, pOther->pev );
WRITE_BYTE( pPlayer->m_iRuneStatus );
MESSAGE_END();
// And Remove this entity
UTIL_Remove( this );
}
void CItemRune::RuneRespawn()
{
edict_t *pentSpawnSpot;
vec3_t vOrigin;
pentSpawnSpot = RuneSelectSpawnPoint();
vOrigin = VARS( pentSpawnSpot )->origin;
UTIL_SetOrigin( pev, vOrigin );
if( dropped )
PrintRespawnMessage();
Spawn();
}
void CResistRune::PrintTouchMessage( CBasePlayer *pPlayer )
{
ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "You got the rune of Resistance!\n" );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Found_ResistRune\"\n",
STRING(pPlayer->pev->netname),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
pPlayer->m_szTeamName );
}
void CResistRune::PrintRespawnMessage()
{
UTIL_LogPrintf( "\"<-1><><>\" triggered \"Respawn_ResistRune\"\n" );
}
void CResistRune::Spawn()
{
SET_MODEL( ENT( pev ), "models/rune_resist.mdl" );
m_iRuneFlag = ITEM_RUNE1_FLAG;
CItemRune::Spawn();
}
LINK_ENTITY_TO_CLASS( item_rune1, CResistRune );
void CStrengthRune::PrintTouchMessage( CBasePlayer *pPlayer )
{
ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "You got the rune of Strength!\n" );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Found_StrengthRune\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
pPlayer->m_szTeamName );
}
void CStrengthRune::PrintRespawnMessage()
{
UTIL_LogPrintf( "\"<-1><><>\" triggered \"Respawn_StrengthRune\"\n" );
}
void CStrengthRune::Spawn()
{
SET_MODEL( ENT( pev ), "models/rune_strength.mdl" );
m_iRuneFlag = ITEM_RUNE2_FLAG;
CItemRune::Spawn();
}
LINK_ENTITY_TO_CLASS( item_rune2, CStrengthRune )
void CHasteRune::PrintTouchMessage( CBasePlayer *pPlayer )
{
ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "You got the rune of Haste!\n" );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Found_HasteRune\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
pPlayer->m_szTeamName );
g_engfuncs.pfnSetClientMaxspeed( ENT( pPlayer->pev ), ( PLAYER_MAX_SPEED * 1.25 ) ); // 25% more speed
}
void CHasteRune::PrintRespawnMessage()
{
UTIL_LogPrintf( "\"<-1><><>\" triggered triggered \"Respawn_HasteRune\"\n" );
}
void CHasteRune::Spawn()
{
SET_MODEL( ENT( pev ), "models/rune_haste.mdl" );
m_iRuneFlag = ITEM_RUNE3_FLAG;
CItemRune::Spawn();
}
LINK_ENTITY_TO_CLASS( item_rune3, CHasteRune )
void CRegenRune::PrintTouchMessage( CBasePlayer *pPlayer )
{
ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "You got the rune of Regeneration!\n" );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Found_RegenRune\"\n",
STRING( pPlayer->pev->netname ),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
pPlayer->m_szTeamName );
}
void CRegenRune::PrintRespawnMessage()
{
UTIL_LogPrintf( "\"<-1><><>\" triggered triggered \"Respawn_RegenRune\"\n" );
}
void CRegenRune::Spawn()
{
SET_MODEL( ENT( pev ), "models/rune_regen.mdl" );
m_iRuneFlag = ITEM_RUNE4_FLAG;
CItemRune::Spawn();
}
LINK_ENTITY_TO_CLASS( item_rune4, CRegenRune )
/*
================
SpawnRunes
spawn all the runes
self is the entity that was created for us, we remove it
================
*/
void SpawnRunes()
{
if( g_bSpawnedRunes )
return;
edict_t *pentSpawnSpot;
pentSpawnSpot = RuneSelectSpawnPoint();
CBaseEntity::Create( "item_rune1", VARS(pentSpawnSpot)->origin, VARS( pentSpawnSpot )->angles, NULL );
pentSpawnSpot = RuneSelectSpawnPoint();
CBaseEntity::Create( "item_rune2", VARS(pentSpawnSpot)->origin, VARS( pentSpawnSpot )->angles, NULL );
pentSpawnSpot = RuneSelectSpawnPoint();
CBaseEntity::Create( "item_rune3", VARS(pentSpawnSpot)->origin, VARS( pentSpawnSpot )->angles, NULL );
pentSpawnSpot = RuneSelectSpawnPoint();
CBaseEntity::Create( "item_rune4", VARS(pentSpawnSpot)->origin, VARS( pentSpawnSpot )->angles, NULL );
g_bSpawnedRunes = TRUE;
}

85
dlls/3wave/runes.h Normal file
View File

@ -0,0 +1,85 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#pragma once
#ifndef RUNES_H
#define RUNES_H
static const char *g_RuneEntityName[] =
{
"",
"item_rune1",
"item_rune2",
"item_rune3",
"item_rune4"
};
static const char *g_RuneName[] =
{
"Unknown",
"ResistRune",
"StrengthRune",
"HasteRune",
"RegenRune"
};
class CItemRune : public CBaseEntity
{
private:
void EXPORT RuneRespawn();
public:
void EXPORT RuneTouch( CBaseEntity *pOther );
void Spawn();
int Classify() { return CLASS_RUNE; };
void EXPORT MakeTouchable();
virtual void PrintTouchMessage( CBasePlayer *pPlayer ){}
virtual void PrintRespawnMessage(){}
int m_iRuneFlag;
bool m_bTouchable;
bool dropped;
};
class CResistRune : public CItemRune
{
public:
void Spawn();
void PrintTouchMessage( CBasePlayer *pPlayer );
void PrintRespawnMessage();
};
class CStrengthRune : public CItemRune
{
public:
void Spawn();
void PrintTouchMessage( CBasePlayer *pPlayer );
void PrintRespawnMessage();
};
class CHasteRune : public CItemRune
{
public:
void Spawn();
void PrintTouchMessage( CBasePlayer *pPlayer );
void PrintRespawnMessage();
};
class CRegenRune : public CItemRune
{
public:
void Spawn();
void PrintTouchMessage( CBasePlayer *pPlayer );
void PrintRespawnMessage();
};
#endif // RUNES_H

File diff suppressed because it is too large Load Diff

View File

@ -12,166 +12,23 @@
* without written permission from Valve LLC.
*
****/
#pragma once
#ifndef THREEWAVE_GAMERULES_H
#define THREEWAVE_GAMERULES_H
#define BLUE 2
#define RED 1
#ifndef NO_VOICEGAMEMGR
#include "voice_gamemgr.h"
#endif
//=========================================================
// Flags
//=========================================================
class CItemFlag : public CBaseEntity
{
public:
void Spawn( void );
BOOL Dropped;
float m_flDroppedTime;
void EXPORT FlagThink( void );
private:
void Precache ( void );
void Capture(CBasePlayer *pPlayer, int iTeam );
void ResetFlag( int iTeam );
void Materialize( void );
void EXPORT FlagTouch( CBaseEntity *pOther );
// BOOL MyTouch( CBasePlayer *pPlayer );
};
class CCarriedFlag : public CBaseEntity
{
public:
void Spawn( void );
CBasePlayer *Owner;
int m_iOwnerOldVel;
private:
void Precache ( void );
void EXPORT FlagThink( void );
};
class CResistRune : public CBaseEntity
{
private:
void EXPORT RuneRespawn ( void );
public:
void EXPORT RuneTouch ( CBaseEntity *pOther );
void Spawn( void );
void EXPORT MakeTouchable ( void );
int m_iRuneFlag;
bool m_bTouchable;
bool dropped;
};
class CStrengthRune : public CBaseEntity
{
private:
void EXPORT RuneRespawn ( void );
public:
void EXPORT RuneTouch ( CBaseEntity *pOther );
void Spawn( void );
void EXPORT MakeTouchable ( void );
int m_iRuneFlag;
bool m_bTouchable;
bool dropped;
};
class CHasteRune : public CBaseEntity
{
private:
void EXPORT RuneRespawn ( void );
public:
void EXPORT RuneTouch ( CBaseEntity *pOther );
void EXPORT MakeTouchable ( void );
void Spawn( void );
int m_iRuneFlag;
bool m_bTouchable;
bool dropped;
};
class CRegenRune : public CBaseEntity
{
private:
void EXPORT RuneRespawn ( void );
public:
void EXPORT RuneTouch ( CBaseEntity *pOther );
void Spawn( void );
void EXPORT MakeTouchable ( void );
int m_iRuneFlag;
bool m_bTouchable;
bool dropped;
};
class CGrapple : public CBaseEntity
{
public:
//Yes, I have no imagination so I use standard touch, spawn and think function names.
//Sue me! =P.
void Spawn ( void );
void EXPORT OnAirThink ( void );
void EXPORT GrappleTouch ( CBaseEntity *pOther );
void Reset_Grapple ( void );
void EXPORT Grapple_Track ( void );
float m_flNextIdleTime;
};
#define STEAL_SOUND 1
#define CAPTURE_SOUND 2
#define RETURN_SOUND 3
#define RED_FLAG_STOLEN 1
#define BLUE_FLAG_STOLEN 2
#define RED_FLAG_CAPTURED 3
#define BLUE_FLAG_CAPTURED 4
#define RED_FLAG_RETURNED_PLAYER 5
#define BLUE_FLAG_RETURNED_PLAYER 6
#define RED_FLAG_RETURNED 7
#define BLUE_FLAG_RETURNED 8
#define RED_FLAG_LOST 9
#define BLUE_FLAG_LOST 10
#define RED_FLAG_STOLEN 1
#define BLUE_FLAG_STOLEN 2
#define RED_FLAG_DROPPED 3
#define BLUE_FLAG_DROPPED 4
#define RED_FLAG_ATBASE 5
#define BLUE_FLAG_ATBASE 6
extern int gmsgCTFMsgs;
extern int gmsgShowMenu;
extern int gmsgFlagStatus;
extern int gmsgRuneStatus;
extern int gmsgFlagCarrier;
extern int gmsgScoreInfo;
#define MAX_TEAMNAME_LENGTH 16
#define MAX_TEAMS 32
@ -223,10 +80,11 @@ public:
float m_flFlagStatusTime;
private:
void RecountTeams( void );
void RecountTeams();
BOOL m_DisableDeathMessages;
BOOL m_DisableDeathPenalty;
BOOL m_teamLimit; // This means the server set only some teams as valid
char m_szTeamList[TEAMPLAY_TEAMLISTLENGTH];
};
#endif // THREEWAVE_GAMERULES_H

View File

@ -37,6 +37,9 @@ else()
endif()
set (SVDLL_SOURCES
3wave/flags.cpp
3wave/grapple.cpp
3wave/runes.cpp
3wave/threewave_gamerules.cpp
aghl/agarena.cpp
aghl/agglobal.cpp

View File

@ -104,6 +104,8 @@ typedef void(CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCalle
#define CLASS_PLAYER_ALLY 11
#define CLASS_PLAYER_BIOWEAPON 12 // hornets and snarks.launched by players
#define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace
#define CLASS_PROJECTILE 14
#define CLASS_RUNE 15
#define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
class CBaseEntity;

View File

@ -65,7 +65,6 @@ int CQuakeGun::GetItemInfo(ItemInfo *p)
void CQuakeGun::DestroyEffect( void )
{
#ifndef CLIENT_DLL
if ( m_pBeam )
{
@ -73,12 +72,10 @@ void CQuakeGun::DestroyEffect( void )
m_pBeam = NULL;
}
#endif
}
void CQuakeGun::CreateEffect( void )
{
#ifndef CLIENT_DLL
DestroyEffect();
@ -93,7 +90,6 @@ void CQuakeGun::CreateEffect( void )
m_pBeam->SetScrollRate( 110 );
m_pBeam->SetNoise( 5 );
#endif
}
void CQuakeGun::UpdateEffect( void )
@ -146,25 +142,23 @@ BOOL CQuakeGun::Deploy( )
// Plays quad sound if needed
int CQuakeGun::SuperDamageSound()
{
if( m_pPlayer->m_iQuakeItems & IT_QUAD )
if( m_pPlayer->m_flNextQuadSound < gpGlobals->time )
{
if( m_pPlayer->m_flNextQuadSound < gpGlobals->time)
if( m_pPlayer->m_iQuakeItems & IT_QUAD )
{
m_pPlayer->m_flNextQuadSound = gpGlobals->time + 1;
return ( m_pPlayer->m_iRuneStatus == ITEM_RUNE2_FLAG ) ? 3 : 1;
}
}
else if( m_pPlayer->m_iRuneStatus == ITEM_RUNE2_FLAG
&& m_pPlayer->m_flNextQuadSound < gpGlobals->time )
{
m_pPlayer->m_flNextQuadSound = gpGlobals->time + 1;
return 2;
}
else if( m_pPlayer->m_iRuneStatus == ITEM_RUNE3_FLAG
&& m_pPlayer->m_flNextQuadSound < gpGlobals->time )
{
m_pPlayer->m_flNextQuadSound = gpGlobals->time + 1;
return 4;
else if( m_pPlayer->m_iRuneStatus == ITEM_RUNE2_FLAG )
{
m_pPlayer->m_flNextQuadSound = gpGlobals->time + 1;
return 2;
}
else if( m_pPlayer->m_iRuneStatus == ITEM_RUNE3_FLAG )
{
m_pPlayer->m_flNextQuadSound = gpGlobals->time + 1;
return 4;
}
}
return 0;
}

View File

@ -904,7 +904,7 @@ void CItemAmmoShells::Spawn( void )
class CItemAmmoSpikes : public CItemAmmo
{
public:
void Spawn( void );
void Spawn();
};
LINK_ENTITY_TO_CLASS(item_spikes, CItemAmmoSpikes);

View File

@ -72,7 +72,7 @@ void CQuakeNail::Spawn( void )
// Model
SET_MODEL( ENT(pev), "models/spike.mdl" );
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
UTIL_SetSize( pev, g_vecZero, g_vecZero );
UTIL_SetOrigin( pev, pev->origin );
// Damage
@ -117,6 +117,3 @@ void CQuakeNail::NailTouch( CBaseEntity *pOther )
UTIL_Remove( this );
}

View File

@ -112,7 +112,7 @@ void CQuakeRocket::Spawn( void )
{
Precache();
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
UTIL_SetSize(pev, g_vecZero, g_vecZero );
UTIL_SetOrigin( pev, pev->origin );
}
@ -155,15 +155,14 @@ void CQuakeRocket::GrenadeTouch( CBaseEntity *pOther )
}
if (pev->flags & FL_ONGROUND)
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.75;
if (pev->velocity.Length() <= 20)
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.75;
if (pev->velocity.Length() <= 20)
{
pev->avelocity = g_vecZero;
}
pev->avelocity = g_vecZero;
}
}
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);

View File

@ -17,6 +17,7 @@
#define PLAYER_H
#include "pm_materials.h"
#include "grapple.h"
#define PLAYER_FATAL_FALL_SPEED 1024// approx 60 feet
#define PLAYER_MAX_SAFE_FALL_SPEED 580// approx 20 feet
@ -472,7 +473,7 @@ public:
bool m_bHook_Out;
bool m_bOn_Hook;
CBaseEntity *m_ppHook;
CGrapple *m_ppHook;
void Service_Grapple();
};

View File

@ -460,9 +460,10 @@ void Q_RadiusDamage( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDa
class CQuakeRocket : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
void Explode( void );
void Spawn();
void Precache();
void Explode();
int Classify() { return CLASS_PROJECTILE; };
// Rocket funcs
static CQuakeRocket *CreateRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
@ -480,7 +481,8 @@ public:
class CQuakeNail : public CBaseEntity
{
public:
void Spawn( void );
void Spawn();
int Classify() { return CLASS_PROJECTILE; };
static CQuakeNail *CreateNail( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
static CQuakeNail *CreateSuperNail( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
void EXPORT NailTouch( CBaseEntity *pOther );