You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1431 lines
33 KiB
1431 lines
33 KiB
/*** |
|
* |
|
* 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. |
|
* |
|
****/ |
|
|
|
#include "extdll.h" |
|
#include "util.h" |
|
#include "cbase.h" |
|
#include "monsters.h" |
|
#include "weapons.h" |
|
#include "nodes.h" |
|
#include "player.h" |
|
#include "gamerules.h" |
|
#include "soundent.h" |
|
#include "effects.h" |
|
#include "rpg.h" |
|
#include "shake.h" |
|
|
|
extern int gmsgRpgViseur; |
|
extern int gmsgRpgMenu; |
|
extern int gmsgClientDecal; |
|
extern int gEvilImpulse101; |
|
|
|
|
|
|
|
#if !CLIENT_DLL |
|
|
|
extern short g_sModelIndexBlastCircle; |
|
extern void EnvSmokeCreate( const Vector ¢er, int m_iScale, float m_fFrameRate, int m_iTime, int m_iEndTime ); |
|
|
|
//------------------------------------------ |
|
// |
|
// Sauvegardes |
|
// |
|
//------------------------------------------ |
|
|
|
// CRpg |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_rpg, CRpg ); |
|
|
|
TYPEDESCRIPTION CRpg::m_SaveData[] = |
|
{ |
|
DEFINE_FIELD( CRpg, m_cActiveRockets, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpg, m_pEntityTarget, FIELD_CLASSPTR ), |
|
DEFINE_FIELD( CRpg, m_pEntityLocked, FIELD_CLASSPTR ), |
|
DEFINE_FIELD( CRpg, m_flLockTime, FIELD_TIME ), |
|
DEFINE_FIELD( CRpg, m_iAmmoType, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpg, m_iAmmoRocket, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpg, m_iAmmoElectro, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpg, m_iAmmoNuclear, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpg, m_iMenuState, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpg, m_bLoaded, FIELD_BOOLEAN ), |
|
DEFINE_FIELD( CRpg, m_bRpgUpdate, FIELD_BOOLEAN ), |
|
DEFINE_FIELD( CRpg, m_flReloadTime, FIELD_FLOAT ), |
|
DEFINE_FIELD( CRpg, m_flLastBip, FIELD_TIME ), |
|
}; |
|
|
|
|
|
// CRpgRocket |
|
|
|
LINK_ENTITY_TO_CLASS( rpg_rocket, CRpgRocket ); |
|
|
|
TYPEDESCRIPTION CRpgRocket::m_SaveData[] = |
|
{ |
|
DEFINE_FIELD( CRpgRocket, m_flIgniteTime, FIELD_TIME ), |
|
DEFINE_FIELD( CRpgRocket, m_pTargetMonster, FIELD_CLASSPTR ), |
|
DEFINE_FIELD( CRpgRocket, m_iRocketType, FIELD_INTEGER ), |
|
DEFINE_FIELD( CRpgRocket, m_flDiskTime, FIELD_TIME ), |
|
DEFINE_FIELD( CRpgRocket, m_flLastRadius, FIELD_FLOAT ), |
|
|
|
}; |
|
IMPLEMENT_SAVERESTORE( CRpgRocket, CGrenade ); |
|
|
|
//------------------------------------------------- |
|
//------------------------------------------------ |
|
// |
|
// CRpgRocket |
|
// |
|
//------------------------------------------------- |
|
//------------------------------------------------- |
|
|
|
|
|
//------------------------------------------------ |
|
// |
|
// Creation de la roquette |
|
// |
|
//------------------------------------------------- |
|
CRpgRocket *CRpgRocket::CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher ) |
|
{ |
|
CRpgRocket *pRocket = GetClassPtr( (CRpgRocket *)NULL ); |
|
|
|
UTIL_SetOrigin( pRocket->pev, vecOrigin ); |
|
pRocket->pev->angles = vecAngles; |
|
|
|
if ( pLauncher != NULL ) //modif de Julien |
|
{ |
|
pRocket->m_pLauncher = pLauncher;// remember what RPG fired me. |
|
pRocket->m_iRocketType = pLauncher->m_iAmmoType; |
|
} |
|
else |
|
pRocket->m_pLauncher = NULL; |
|
|
|
pRocket->Spawn(); |
|
pRocket->SetTouch( &CRpgRocket::RocketTouch ); |
|
|
|
if ( pOwner != NULL ) |
|
pRocket->pev->owner = pOwner->edict(); |
|
else |
|
pRocket->pev->owner = NULL; |
|
|
|
return pRocket; |
|
} |
|
|
|
//========================================================= |
|
//========================================================= |
|
void CRpgRocket::Spawn( void ) |
|
{ |
|
Precache(); |
|
|
|
pev->movetype = MOVETYPE_BOUNCE; |
|
pev->solid = SOLID_BBOX; |
|
|
|
// model |
|
|
|
if ( m_iRocketType == AMMO_ELECTRO ) |
|
SET_MODEL(ENT(pev), "models/rpg_electrocket.mdl" ); |
|
else if ( m_iRocketType == AMMO_NUCLEAR ) |
|
SET_MODEL(ENT(pev), "models/rpg_nuclearrocket.mdl" ); |
|
else |
|
SET_MODEL(ENT(pev), "models/rpgrocket.mdl"); |
|
|
|
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) ); |
|
UTIL_SetOrigin( pev, pev->origin ); |
|
|
|
pev->classname = MAKE_STRING( "rpg_rocket" ); |
|
|
|
SetThink( &CRpgRocket::IgniteThink ); |
|
pev->nextthink = gpGlobals->time + 0.1; //modif de Julien : 0.4 |
|
|
|
pev->angles.x -= 30.0f; |
|
UTIL_MakeVectors( pev->angles ); |
|
pev->angles.x = -( pev->angles.x + 30.0f ); |
|
|
|
pev->velocity = gpGlobals->v_forward * 250.0f; |
|
pev->gravity = 0.5f; |
|
|
|
|
|
pev->dmg = gSkillData.plrDmgRPG; |
|
|
|
pev->takedamage = DAMAGE_NO; // fix bug |
|
} |
|
|
|
|
|
void CRpgRocket :: Precache( void ) |
|
{ |
|
PRECACHE_MODEL("models/rpgrocket.mdl"); |
|
PRECACHE_MODEL("models/rpg_electrocket.mdl"); |
|
PRECACHE_MODEL("models/rpg_nuclearrocket.mdl"); |
|
|
|
PRECACHE_SOUND ("weapons/rocket1.wav"); |
|
PRECACHE_SOUND ( "weapons/mortarhit.wav" ); |
|
PRECACHE_SOUND ( "weapons/rpg_electrocket.wav" ); |
|
|
|
m_iTrail = PRECACHE_MODEL("sprites/smoke.spr"); |
|
m_iDiskTexture = PRECACHE_MODEL("sprites/rpg_disk.spr"); |
|
m_sNuclearSprite = PRECACHE_MODEL("sprites/fexplo.spr"); |
|
} |
|
|
|
|
|
//------------------------------------------------ |
|
// |
|
// Explosion de la roquette |
|
// |
|
//------------------------------------------------- |
|
|
|
|
|
void CRpgRocket :: RocketTouch ( CBaseEntity *pOther ) //modif de Julien |
|
{ |
|
|
|
|
|
//modif de Julien |
|
if ( m_pTargetMonster != NULL && m_pLauncher && m_pLauncher->m_cActiveRockets == 1 ) |
|
{ |
|
if ( pOther == m_pTargetMonster ) |
|
m_pLauncher->UpdateCrosshair ( RPG_TEXT_TOUCHE ); |
|
else |
|
m_pLauncher->UpdateCrosshair ( RPG_TEXT_MANQUE ); |
|
|
|
m_pLauncher->m_cActiveRockets = 0; |
|
} |
|
|
|
// enflamme le gaz |
|
|
|
if ( IsInGaz() == TRUE ) |
|
{ |
|
edict_t *pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "player" ); |
|
CBaseEntity *pPlayer = CBaseEntity::Instance ( pFind ); |
|
pPlayer->m_bFireInGaz = TRUE; |
|
} |
|
|
|
|
|
switch ( m_iRocketType ) |
|
{ |
|
case AMMO_ROCKET: |
|
{ |
|
pev->origin = pev->origin - pev->velocity * 0.05; // revient un peu en arriere pour ne pas exploser du sol |
|
ExplodeTouch( pOther ); |
|
break; |
|
} |
|
|
|
case AMMO_ELECTRO: |
|
{ |
|
// truc affreux pour creer une particule a travers ce message pour les decals |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgClientDecal ); |
|
|
|
WRITE_COORD( pev->origin.x ); // xyz source |
|
WRITE_COORD( pev->origin.y ); |
|
WRITE_COORD( pev->origin.z ); |
|
WRITE_COORD( 0 ); // xyz norme |
|
WRITE_COORD( 0 ); |
|
WRITE_COORD( 0 ); |
|
WRITE_CHAR ( 'a' ); // type de texture |
|
WRITE_BYTE ( 4 ); // 4 == electro-rocket |
|
|
|
MESSAGE_END(); |
|
|
|
SetThink ( &CRpgRocket::ElectroThink ); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
m_flDiskTime = gpGlobals->time; |
|
m_flLastRadius = 0.0; // pour coller avec la dll client |
|
|
|
pev->effects = 0; |
|
|
|
UTIL_ScreenFadeAll ( Vector ( 215, 225, 255 ), 0.3, 0, 80, FFADE_IN ); |
|
|
|
// fait du bruit pour r |
|
|
|
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/rpg_electrocket.wav", 1, ATTN_NONE); |
|
|
|
|
|
break; |
|
} |
|
|
|
case AMMO_NUCLEAR: |
|
{ |
|
// explosion |
|
|
|
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); |
|
WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound |
|
WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound |
|
WRITE_COORD( pev->origin.y ); |
|
WRITE_COORD( pev->origin.z + 200 ); |
|
WRITE_SHORT( m_sNuclearSprite ); |
|
WRITE_BYTE( 100 ); // scale * 10 |
|
WRITE_BYTE( 10 ); // framerate |
|
WRITE_BYTE( TE_EXPLFLAG_NONE ); |
|
MESSAGE_END(); |
|
|
|
// cercles |
|
|
|
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); |
|
WRITE_BYTE( TE_BEAMCYLINDER ); |
|
WRITE_COORD( pev->origin.x); |
|
WRITE_COORD( pev->origin.y); |
|
WRITE_COORD( pev->origin.z); |
|
WRITE_COORD( pev->origin.x); |
|
WRITE_COORD( pev->origin.y); |
|
WRITE_COORD( pev->origin.z + 600 * 5 ); // reach damage radius over .3 seconds |
|
WRITE_SHORT( g_sModelIndexBlastCircle ); |
|
WRITE_BYTE( 0 ); // startframe |
|
WRITE_BYTE( 0 ); // framerate |
|
WRITE_BYTE( 3 ); // life |
|
WRITE_BYTE( 128 ); // width |
|
WRITE_BYTE( 0 ); // noise |
|
WRITE_BYTE( 255 ); // rgb |
|
WRITE_BYTE( 255 ); |
|
WRITE_BYTE( 200 ); |
|
WRITE_BYTE( 170 ); //brightness |
|
WRITE_BYTE( 0 ); // speed |
|
MESSAGE_END(); |
|
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); |
|
WRITE_BYTE( TE_BEAMCYLINDER ); |
|
WRITE_COORD( pev->origin.x); |
|
WRITE_COORD( pev->origin.y); |
|
WRITE_COORD( pev->origin.z + 32 ); |
|
WRITE_COORD( pev->origin.x); |
|
WRITE_COORD( pev->origin.y); |
|
WRITE_COORD( pev->origin.z - 600 * 5 / 2 ); // reach damage radius over .3 seconds |
|
WRITE_SHORT( g_sModelIndexBlastCircle ); |
|
WRITE_BYTE( 0 ); // startframe |
|
WRITE_BYTE( 0 ); // framerate |
|
WRITE_BYTE( 4 ); // life |
|
WRITE_BYTE( 48 ); // width |
|
WRITE_BYTE( 0 ); // noise |
|
WRITE_BYTE( 255 ); // rgb |
|
WRITE_BYTE( 255 ); |
|
WRITE_BYTE( 200 ); |
|
WRITE_BYTE( 170 ); //brightness |
|
WRITE_BYTE( 0 ); // speed |
|
MESSAGE_END(); |
|
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/mortarhit.wav", 1, ATTN_NONE); |
|
|
|
|
|
UTIL_ScreenFadeAll ( Vector ( 220, 220, 220 ), 0.2, 0.3, 130, FFADE_IN ); |
|
UTIL_ScreenShakeAll ( pev->origin, 200, 100, 3 ); |
|
|
|
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, BIG_EXPLOSION_VOLUME, 3.0 ); |
|
|
|
// dommages |
|
|
|
float flRadius = 1000; |
|
|
|
CBaseEntity *pEntity = NULL; |
|
float flDamage = 400; |
|
|
|
while ((pEntity = UTIL_FindEntityInSphere( pEntity, pev->origin, flRadius )) != NULL) |
|
{ |
|
if ( pEntity->pev->takedamage != DAMAGE_NO ) |
|
{ |
|
Vector vecSpot = pEntity->Center(); |
|
TraceResult tr; |
|
UTIL_TraceLine ( pev->origin, vecSpot, dont_ignore_monsters, ENT(pev), &tr ); |
|
|
|
if ( tr.flFraction != 1.0 && tr.pHit != pEntity->edict() ) |
|
{ |
|
flDamage = flDamage * (pev->origin - vecSpot).Length() / 3 * flRadius; |
|
} |
|
|
|
pEntity->TakeDamage ( pev, pev, flDamage, DMG_RADIATION ); |
|
} |
|
} |
|
|
|
SetThink ( &CBaseEntity::SUB_Remove ); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
|
|
// d |
|
|
|
CBaseEntity *pTrigger = UTIL_FindEntityByClassname ( NULL, "trigger_nuclear" ); |
|
|
|
while ( pTrigger != NULL ) |
|
{ |
|
|
|
Vector org = pev->origin, min = pTrigger->pev->absmin, max = pTrigger->pev->absmax; |
|
|
|
if (( org.x > min.x && org.x < max.x ) && |
|
( org.y > min.y && org.y < max.y ) && |
|
( org.z > min.z && org.z < max.z ) ) |
|
{ |
|
FireTargets ( STRING(pTrigger->pev->target), this, this, USE_ON, 0 ); |
|
} |
|
|
|
pTrigger = UTIL_FindEntityByClassname ( pTrigger, "trigger_nuclear" ); |
|
} |
|
|
|
|
|
|
|
break; |
|
} |
|
} |
|
|
|
pev->movetype = MOVETYPE_NOCLIP; // bug de la trainee de fumee rebondissante |
|
pev->solid = SOLID_NOT; |
|
pev->velocity = Vector ( 0,0,0 ); |
|
|
|
STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" ); |
|
} |
|
|
|
|
|
int CRpgRocket :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) |
|
{ return 1; } |
|
|
|
void CRpgRocket :: Killed( entvars_t *pevAttacker, int iGib ) |
|
{ }; |
|
|
|
|
|
void CRpgRocket :: ElectroThink ( void ) |
|
{ |
|
if ( m_flLastRadius > ELECTRO_DISK_MAX ) |
|
{ |
|
SetThink ( &CBaseEntity::SUB_Remove ); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
return; |
|
} |
|
|
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
float flRadius = ( gpGlobals->time - m_flDiskTime ) * ELECTRO_DISK_SPEED + 1; // +1 pour coller avec la dll client |
|
|
|
CBaseEntity *pEntity = NULL; |
|
float flDamage = 100; |
|
|
|
while ((pEntity = UTIL_FindEntityInSphere( pEntity, pev->origin, flRadius )) != NULL) |
|
{ |
|
if ( pEntity->pev->takedamage != DAMAGE_NO ) |
|
{ |
|
Vector2D vecSpot = ( pev->origin - pEntity->Center() ).Make2D(); |
|
|
|
if ( vecSpot.Length() > m_flLastRadius && |
|
( |
|
( pEntity->pev->solid == SOLID_BSP && pEntity->pev->mins.z <= pev->origin.z && pEntity->pev->maxs.z >= pev->origin.z ) |
|
|| |
|
( pEntity->pev->solid != SOLID_BSP && pEntity->pev->absmin.z <= pev->origin.z && pEntity->pev->absmax.z >= pev->origin.z ) |
|
) |
|
) |
|
|
|
{ |
|
pEntity->TakeDamage ( pev, pev, flDamage, DMG_SHOCK ); |
|
|
|
if ( pEntity->IsPlayer () ) |
|
{ |
|
short sens = RANDOM_LONG ( 0, 1 ); |
|
sens = sens == 0 ? -1 : 1; |
|
pEntity->pev->punchangle.y = 25 * sens; |
|
pEntity->pev->punchangle.x = 25 * sens; |
|
} |
|
} |
|
} |
|
} |
|
|
|
m_flLastRadius = flRadius; |
|
} |
|
|
|
//------------------------------------------------ |
|
// |
|
// Mouvement de la roquette |
|
// |
|
//------------------------------------------------- |
|
|
|
|
|
void CRpgRocket::IgniteThink( void ) |
|
{ |
|
|
|
pev->movetype = MOVETYPE_FLY; |
|
|
|
if ( m_iRocketType == AMMO_ROCKET ) |
|
pev->effects |= EF_LIGHT; |
|
|
|
|
|
// make rocket sound |
|
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/rocket1.wav", 1, 0.5f ); |
|
|
|
if ( m_iRocketType == AMMO_ROCKET || m_iRocketType == AMMO_ELECTRO ) |
|
{ |
|
// rocket trail |
|
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); |
|
WRITE_BYTE( TE_BEAMFOLLOW ); |
|
WRITE_SHORT(entindex()); // entity |
|
WRITE_SHORT(m_iTrail ); // model |
|
WRITE_BYTE( 40 ); // life |
|
WRITE_BYTE( 5 ); // width |
|
WRITE_BYTE( 224 ); // r, g, b |
|
WRITE_BYTE( 224 ); // r, g, b |
|
WRITE_BYTE( 255 ); // r, g, b |
|
|
|
if ( m_iRocketType == AMMO_ROCKET ) |
|
WRITE_BYTE( 255 ); // brightness |
|
else |
|
WRITE_BYTE( 100 ); // brightness |
|
|
|
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS) |
|
} |
|
|
|
|
|
m_flIgniteTime = gpGlobals->time; |
|
|
|
// set to follow laser spot |
|
SetThink( &CRpgRocket::FollowThink ); |
|
pev->nextthink = gpGlobals->time + 0.1f; |
|
} |
|
|
|
void CRpgRocket::FollowThink( void ) |
|
{ |
|
CBaseEntity *pOther = NULL; |
|
Vector vecTarget; |
|
Vector vecDir; |
|
Vector angDir; |
|
TraceResult tr; |
|
|
|
UTIL_MakeAimVectors( pev->angles ); |
|
|
|
vecTarget = gpGlobals->v_forward; |
|
|
|
|
|
if ( m_pTargetMonster != NULL ) |
|
{ |
|
pOther = m_pTargetMonster; |
|
UTIL_TraceLine ( pev->origin, pOther->Center(), dont_ignore_monsters, ENT(pev), &tr ); |
|
|
|
if( tr.flFraction >= 0.9f ) |
|
{ |
|
vecDir = ( pOther->Center() - pev->origin ).Normalize(); |
|
angDir = UTIL_VecToAngles( vecDir ); |
|
|
|
|
|
if ( (CBaseEntity::Instance(pev->owner)) ->IsPlayer() ) |
|
vecTarget = vecDir/* * 100*/; |
|
|
|
else |
|
{ |
|
float flAngDistX = UTIL_AngleDiff ( angDir.x, pev->angles.x ); |
|
float flAngDistY = UTIL_AngleDiff ( angDir.y, pev->angles.y ); |
|
|
|
if ( fabs(flAngDistX) < 45 && fabs(flAngDistY) < 45 ) |
|
{ |
|
|
|
if ( fabs(flAngDistX) <= 9 && fabs(flAngDistY) <= 9 ) |
|
{ |
|
vecTarget = vecDir; |
|
} |
|
else |
|
{ |
|
angDir = pev->angles; |
|
int iSens = flAngDistX > 0 ? 1 : -1; |
|
angDir.x = angDir.x + flAngDistX / 2 * iSens; |
|
iSens = flAngDistY > 0 ? 1 : -1; |
|
angDir.y = angDir.y + flAngDistY / 2 * iSens; |
|
|
|
UTIL_MakeVectors( angDir ); |
|
vecTarget = gpGlobals->v_forward; |
|
} |
|
} |
|
else |
|
{ |
|
m_pTargetMonster = NULL; |
|
} |
|
} |
|
} |
|
} |
|
|
|
pev->angles = UTIL_VecToAngles( vecTarget ); |
|
|
|
// this acceleration and turning math is totally wrong, but it seems to respond well so don't change it. |
|
float flSpeed = pev->velocity.Length(); |
|
if( gpGlobals->time - m_flIgniteTime < 1.0f ) |
|
{ |
|
pev->velocity = pev->velocity * 0.2f + vecTarget * ( flSpeed * 0.8f + 400.0f ); |
|
if( pev->waterlevel == 3 ) |
|
{ |
|
// go slow underwater |
|
if( pev->velocity.Length() > 300.0f ) |
|
{ |
|
pev->velocity = pev->velocity.Normalize() * 300.0f; |
|
} |
|
UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1f, pev->origin, 4 ); |
|
} |
|
else |
|
{ |
|
if( pev->velocity.Length() > 2000.0f ) |
|
{ |
|
pev->velocity = pev->velocity.Normalize() * 2000.0f; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if( pev->effects & EF_LIGHT ) |
|
{ |
|
pev->effects = 0; |
|
STOP_SOUND( ENT( pev ), CHAN_VOICE, "weapons/rocket1.wav" ); |
|
} |
|
pev->velocity = pev->velocity * 0.2f + vecTarget * flSpeed * 0.798f; |
|
if( pev->waterlevel == 0 && pev->velocity.Length() < 1500.0f ) |
|
{ |
|
//if( CRpg *pLauncher = (CRpg*)( (CBaseEntity*)( m_hLauncher ) ) ) |
|
if ( m_pLauncher ) //modif de Julien o para Julien, LOL :D |
|
{ |
|
// my launcher is still around, tell it I'm dead. |
|
m_pLauncher->m_cActiveRockets--; //lacked m_ before pLauncher |
|
} |
|
Detonate(); |
|
} |
|
} |
|
|
|
//modif de JUlien |
|
|
|
if ( CBaseEntity::Instance( pev->owner )->IsPlayer() ) |
|
CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin, pev->velocity.Length( ), 0.1 ); |
|
|
|
pev->nextthink = gpGlobals->time + 0.1f; |
|
} |
|
#endif |
|
|
|
|
|
//------------------------------------------------- |
|
//------------------------------------------------- |
|
//------------------------------------------------ |
|
// |
|
// CRpg |
|
// |
|
//------------------------------------------------- |
|
//------------------------------------------------- |
|
//------------------------------------------------- |
|
|
|
|
|
|
|
|
|
void CRpg::Spawn( ) |
|
{ |
|
Precache( ); |
|
m_iId = WEAPON_RPG; |
|
SET_MODEL(ENT(pev), "models/w_rpg.mdl"); |
|
|
|
|
|
m_iClip = 1; // empeche le declenchement du rechargement par la classe mere |
|
|
|
|
|
m_iAmmoType = AMMO_ROCKET; |
|
m_bLoaded = TRUE; //pas de rechargement la premiere fois |
|
m_flReloadTime = -1; // -1 = pas en cours de rechargement |
|
pev->body = RPG_WEAPON_ROCKET; |
|
|
|
|
|
m_iMenuState = 0; |
|
m_iMenuState |= ( RPG_MENU_ROCKET_SELECTED | RPG_MENU_ROCKET_EMPTY | RPG_MENU_ELECTRO_EMPTY | RPG_MENU_NUCLEAR_EMPTY ); |
|
|
|
m_iDefaultAmmo = RPG_DEFAULT_GIVE; |
|
|
|
m_flLastBip = 0; |
|
|
|
|
|
FallInit();// get ready to fall down. |
|
} |
|
|
|
void CRpg::Precache( void ) |
|
{ |
|
PRECACHE_MODEL( "models/w_rpg.mdl" ); |
|
PRECACHE_MODEL( "models/v_rpg.mdl" ); |
|
PRECACHE_MODEL( "models/p_rpg.mdl" ); |
|
|
|
PRECACHE_SOUND( "items/9mmclip1.wav" ); |
|
|
|
PRECACHE_SOUND("sentences/hev_aim_on.wav"); |
|
PRECACHE_SOUND("sentences/hev_aim_off.wav"); |
|
PRECACHE_SOUND( "weapons/rocketfire1.wav" ); |
|
PRECACHE_SOUND( "weapons/glauncher.wav" ); // alternative fire sound |
|
PRECACHE_SOUND("weapons/rpg_lock03.wav"); |
|
|
|
UTIL_PrecacheOther( "rpg_rocket" ); |
|
|
|
// m_usRpg = PRECACHE_EVENT( 1, "events/rpg.sc" ); //modif de Julien, wasn't in Julien's code, commented out (never understood those sc events anyway) |
|
// This event was used in primary attack code, but it got removed anyway. |
|
} |
|
|
|
// /give weapon_rpg |
|
|
|
int CRpg::GetItemInfo( ItemInfo *p ) |
|
{ |
|
p->pszName = STRING( pev->classname ); |
|
p->pszAmmo1 = NULL; //modif de Julien |
|
p->iMaxAmmo1 = ROCKET_MAX_CARRY; |
|
p->pszAmmo2 = NULL; |
|
p->iMaxAmmo2 = -1; |
|
p->iMaxClip = RPG_MAX_CLIP; |
|
p->iSlot = 3; |
|
p->iPosition = 0; |
|
p->iId = m_iId = WEAPON_RPG; |
|
p->iFlags = 0; |
|
p->iWeight = RPG_WEIGHT; |
|
|
|
return 1; |
|
} |
|
|
|
int CRpg::AddToPlayer( CBasePlayer *pPlayer ) |
|
{ |
|
if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); |
|
WRITE_BYTE( m_iId ); |
|
MESSAGE_END(); |
|
|
|
m_pPlayer->TextAmmo( TA_RPG ); |
|
|
|
// ajoute la premi |
|
|
|
AddAmmo ( this, AMMO_ROCKET, 1 ); |
|
|
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
|
|
//------------------------------------------ |
|
// |
|
// Draw / Holster |
|
// |
|
//------------------------------------------ |
|
|
|
|
|
|
|
BOOL CRpg::Deploy() |
|
{ |
|
// d |
|
UpdateMenu (); |
|
|
|
PlayStateSound (); |
|
|
|
if ( m_iAmmoType == AMMO_ROCKET ) |
|
UpdateCrosshair ( RPG_CROSSHAIR_EMPTY ); |
|
else |
|
UpdateCrosshair ( RPG_CROSSHAIR_NORMAL ); |
|
|
|
m_flReloadTime = -1; // -1 = pas en cours de rechargement |
|
|
|
// animation |
|
|
|
BOOL bResult = DefaultDeploy( "models/v_rpg.mdl", "models/p_rpg.mdl", RPG_DRAW, "rpg" ); |
|
|
|
m_flNextPrimaryAttack = gpGlobals->time + 8 / 5.0; |
|
m_flTimeWeaponIdle = gpGlobals->time + 8 / 5.0; |
|
|
|
return bResult; |
|
} |
|
|
|
BOOL CRpg::CanHolster( void ) |
|
{ |
|
if ( m_cActiveRockets ) |
|
return FALSE; |
|
|
|
return TRUE; |
|
} |
|
|
|
void CRpg::Holster( int skiplocal ) |
|
{ |
|
m_fInReload = FALSE;// cancel any reload in progress. |
|
|
|
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5f; |
|
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); |
|
|
|
// fermeture du hud rpg |
|
|
|
m_iMenuState |= RPG_CLOSE; |
|
UpdateMenu (); |
|
m_iMenuState &= ~RPG_CLOSE; |
|
|
|
} |
|
|
|
//------------------------------------------ |
|
// |
|
// Tirs principal et secondaire |
|
// |
|
//------------------------------------------ |
|
|
|
void CRpg::PrimaryAttack() |
|
{ |
|
// confirmation de la selection |
|
|
|
if ( m_iMenuState & RPG_MENU_ACTIVE ) |
|
{ |
|
m_iMenuState &= ~RPG_MENU_ACTIVE; |
|
UpdateMenu(); |
|
|
|
if ( m_iMenuState & RPG_MENU_ROCKET_SELECTED ) |
|
{ |
|
if ( m_iAmmoType != AMMO_ROCKET ) |
|
{ |
|
m_bLoaded = FALSE; |
|
m_flTimeWeaponIdle = gpGlobals->time - 0.1; |
|
} |
|
m_iAmmoType = AMMO_ROCKET; |
|
} |
|
else if ( m_iMenuState & RPG_MENU_ELECTRO_SELECTED ) |
|
{ |
|
if ( m_iAmmoType != AMMO_ELECTRO ) |
|
{ |
|
m_bLoaded = FALSE; |
|
m_flTimeWeaponIdle = gpGlobals->time - 0.1; |
|
} |
|
m_iAmmoType = AMMO_ELECTRO; |
|
} |
|
else if ( m_iMenuState & RPG_MENU_NUCLEAR_SELECTED ) |
|
{ |
|
if ( m_iAmmoType != AMMO_NUCLEAR ) |
|
{ |
|
m_bLoaded = FALSE; |
|
m_flTimeWeaponIdle = gpGlobals->time - 0.1; |
|
} |
|
m_iAmmoType = AMMO_NUCLEAR; |
|
} |
|
|
|
// bon viseur ! |
|
|
|
if ( m_iAmmoType == AMMO_ROCKET ) |
|
UpdateCrosshair ( RPG_CROSSHAIR_EMPTY ); |
|
else |
|
UpdateCrosshair ( RPG_CROSSHAIR_NORMAL ); |
|
|
|
|
|
m_flNextPrimaryAttack = gpGlobals->time + 0.3; |
|
} |
|
|
|
// tir |
|
|
|
else if ( m_bLoaded == TRUE && |
|
((m_iAmmoType == AMMO_ROCKET && m_iAmmoRocket != 0) || |
|
(m_iAmmoType == AMMO_ELECTRO && m_iAmmoElectro != 0) || |
|
(m_iAmmoType == AMMO_NUCLEAR && m_iAmmoNuclear != 0) ) |
|
) |
|
{ |
|
|
|
// flash et son |
|
|
|
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; |
|
m_pPlayer->m_iWeaponFlash = BRIGHT_GUN_FLASH; |
|
m_pPlayer->pev->punchangle.x -= 5; |
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM ); |
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM ); |
|
|
|
// bodygroup |
|
pev->body = RPG_WEAPON_EMPTY; |
|
|
|
#if !CLIENT_DLL |
|
// animations |
|
|
|
// player "shoot" animation |
|
SendWeaponAnim( RPG_FIRE ); |
|
m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); |
|
// roquette |
|
|
|
UTIL_MakeVectors( m_pPlayer->pev->v_angle ); |
|
Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 16.0f + gpGlobals->v_right * 8.0f + gpGlobals->v_up * -8.0f; |
|
|
|
pRocket = CRpgRocket::CreateRpgRocket( vecSrc, m_pPlayer->pev->v_angle, m_pPlayer, this ); |
|
|
|
if ( (m_iAmmoType == AMMO_ROCKET) && ( m_pEntityLocked != NULL ) ) |
|
{ |
|
pRocket->m_pTargetMonster = m_pEntityLocked; |
|
m_cActiveRockets = 1; |
|
} |
|
else |
|
{ |
|
pRocket->m_pTargetMonster = NULL; |
|
m_cActiveRockets = 0; // m_cActiveRockets empeche le rechargement |
|
} |
|
|
|
UTIL_MakeVectors( m_pPlayer->pev->v_angle );// RpgRocket::Create stomps on globals, so remake. |
|
pRocket->pev->velocity = pRocket->pev->velocity + gpGlobals->v_forward * DotProduct( m_pPlayer->pev->velocity, gpGlobals->v_forward ); |
|
#endif |
|
|
|
// munitions |
|
|
|
m_bLoaded = FALSE; |
|
|
|
if ( m_iAmmoType == AMMO_ROCKET ) // A FAIRE : continuer de remplacer les masks par iammotype |
|
{ |
|
m_iAmmoRocket --; |
|
|
|
if ( m_iAmmoRocket == 0 ) |
|
m_iMenuState |= RPG_MENU_ROCKET_EMPTY; |
|
} |
|
else if ( m_iAmmoType == AMMO_ELECTRO ) |
|
{ |
|
m_iAmmoElectro --; |
|
|
|
if ( m_iAmmoElectro == 0 ) |
|
m_iMenuState |= RPG_MENU_ELECTRO_EMPTY; |
|
} |
|
else if ( m_iAmmoType == AMMO_NUCLEAR ) |
|
{ |
|
m_iAmmoNuclear --; |
|
|
|
if ( m_iAmmoNuclear == 0 ) |
|
m_iMenuState |= RPG_MENU_NUCLEAR_EMPTY; |
|
} |
|
|
|
// mise a jour du hud |
|
|
|
UpdateMenu(); |
|
|
|
m_pEntityTarget = m_pEntityLocked = NULL; |
|
m_flLockTime = 0; |
|
|
|
// prochaine attaque |
|
|
|
m_flNextPrimaryAttack = GetNextAttackDelay( 1.5f ); |
|
m_flTimeWeaponIdle = gpGlobals->time + 1.5f; // weaponidle () declenche le rechargement |
|
|
|
ResetEmptySound(); |
|
} |
|
else |
|
{ |
|
PlayEmptySound(); |
|
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2f; |
|
} |
|
} |
|
|
|
void CRpg::SecondaryAttack() |
|
{ |
|
// menu |
|
|
|
if ( !(m_iMenuState & RPG_MENU_ACTIVE) ) |
|
m_iMenuState |= RPG_MENU_ACTIVE; |
|
|
|
else if ( m_iMenuState & RPG_MENU_ROCKET_SELECTED ) |
|
{ |
|
m_iMenuState &= ~RPG_MENU_ROCKET_SELECTED; |
|
|
|
if ( !(m_iMenuState & RPG_MENU_ELECTRO_EMPTY) ) |
|
m_iMenuState |= RPG_MENU_ELECTRO_SELECTED; |
|
|
|
else if ( !(m_iMenuState & RPG_MENU_NUCLEAR_EMPTY) ) |
|
m_iMenuState |= RPG_MENU_NUCLEAR_SELECTED; |
|
|
|
else |
|
m_iMenuState |= RPG_MENU_ROCKET_SELECTED; |
|
} |
|
|
|
|
|
else if ( m_iMenuState & RPG_MENU_ELECTRO_SELECTED ) |
|
{ |
|
m_iMenuState &= ~RPG_MENU_ELECTRO_SELECTED; |
|
|
|
if ( !(m_iMenuState & RPG_MENU_NUCLEAR_EMPTY) ) |
|
m_iMenuState |= RPG_MENU_NUCLEAR_SELECTED; |
|
|
|
else if ( !(m_iMenuState & RPG_MENU_ROCKET_EMPTY) ) |
|
m_iMenuState |= RPG_MENU_ROCKET_SELECTED; |
|
|
|
else |
|
m_iMenuState |= RPG_MENU_ELECTRO_SELECTED; |
|
} |
|
else if ( m_iMenuState & RPG_MENU_NUCLEAR_SELECTED ) |
|
{ |
|
m_iMenuState &= ~RPG_MENU_NUCLEAR_SELECTED; |
|
|
|
if ( !(m_iMenuState & RPG_MENU_ROCKET_EMPTY) ) |
|
m_iMenuState |= RPG_MENU_ROCKET_SELECTED; |
|
|
|
else if ( !(m_iMenuState & RPG_MENU_ELECTRO_EMPTY) ) |
|
m_iMenuState |= RPG_MENU_ELECTRO_SELECTED; |
|
|
|
else |
|
m_iMenuState |= RPG_MENU_NUCLEAR_SELECTED; |
|
} |
|
|
|
UpdateMenu (); |
|
|
|
PlayStateSound (); |
|
|
|
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.2f; |
|
} |
|
|
|
//------------------------------------------ |
|
// |
|
// Rechargement |
|
// |
|
//------------------------------------------ |
|
|
|
|
|
|
|
void CRpg::Reload( void ) |
|
{ |
|
if ( m_cActiveRockets < 0 || m_flTimeWeaponIdle > gpGlobals->time ) // weaponidle () declenche le rechargement |
|
return; |
|
|
|
if ( (m_iAmmoType == AMMO_ROCKET && m_iAmmoRocket == 0) || |
|
(m_iAmmoType == AMMO_ELECTRO && m_iAmmoElectro == 0) || |
|
(m_iAmmoType == AMMO_NUCLEAR && m_iAmmoNuclear == 0) |
|
) |
|
return; |
|
|
|
// bodygroup |
|
// en cas de changement de munition, le bodygroup n'a pas |
|
|
|
pev->body = RPG_WEAPON_EMPTY; |
|
|
|
// animations |
|
|
|
int iAnim; |
|
switch ( m_iAmmoType ) |
|
{ |
|
case AMMO_ROCKET: |
|
iAnim = RPG_RELOAD_ROCKET; |
|
m_flReloadTime = gpGlobals->time + 2; |
|
break; |
|
|
|
case AMMO_ELECTRO: |
|
iAnim = RPG_RELOAD_ELECTRO; |
|
m_flReloadTime = gpGlobals->time + 4; |
|
break; |
|
|
|
case AMMO_NUCLEAR: |
|
iAnim = RPG_RELOAD_NUCLEAR; |
|
m_flReloadTime = gpGlobals->time + 6; |
|
break; |
|
} |
|
|
|
SendWeaponAnim( iAnim ); |
|
|
|
// validation du rechargement |
|
|
|
m_flTimeWeaponIdle = gpGlobals->time + 10; |
|
m_flNextPrimaryAttack = gpGlobals->time + 10; |
|
|
|
} |
|
|
|
void CRpg::WeaponIdle( void ) |
|
{ |
|
// rafraichissement des donnees client |
|
|
|
if ( m_bRpgUpdate == 1 ) |
|
{ |
|
UpdateMenu (); |
|
|
|
if ( m_iAmmoType == AMMO_ROCKET ) |
|
UpdateCrosshair ( RPG_CROSSHAIR_EMPTY ); |
|
else |
|
UpdateCrosshair ( RPG_CROSSHAIR_NORMAL ); |
|
|
|
m_flTimeWeaponIdle = gpGlobals->time - 0.1; // pour charger une anim et changer le bodygroup |
|
m_bRpgUpdate = 0; // weaponidle, ca rafraichit, et c'est d |
|
} |
|
|
|
// viseur |
|
|
|
if ( (m_iAmmoType == AMMO_ROCKET) && ( m_cActiveRockets == 0 ) ) |
|
UpdateEntityTarget (); |
|
|
|
//ALARM! DIFFERENT CODE DETECTED! |
|
ResetEmptySound( ); |
|
|
|
// rechargement |
|
|
|
if ( m_flTimeWeaponIdle < gpGlobals->time && m_bLoaded == FALSE && m_flReloadTime == -1 ) // -1 = pas en cours de rechargement |
|
{ |
|
Reload (); |
|
return; // pour ne pas lancer d anim idle |
|
} |
|
|
|
else if ( m_bLoaded == FALSE && m_flReloadTime != -1 && m_flReloadTime < gpGlobals->time ) |
|
{ |
|
m_bLoaded = TRUE; |
|
m_flReloadTime = -1; |
|
m_flNextPrimaryAttack = gpGlobals->time; |
|
m_flTimeWeaponIdle = gpGlobals->time; |
|
} |
|
|
|
|
|
// ajustement du bodygroup |
|
|
|
if ( m_flTimeWeaponIdle <= gpGlobals->time ) |
|
{ |
|
int ibody; |
|
switch ( m_iAmmoType ) |
|
{ |
|
case AMMO_ROCKET: |
|
ibody = RPG_WEAPON_ROCKET; break; |
|
case AMMO_ELECTRO: |
|
ibody = RPG_WEAPON_ELECTRO; break; |
|
case AMMO_NUCLEAR: |
|
ibody = RPG_WEAPON_NUCLEAR; break; |
|
} |
|
if ( m_bLoaded == FALSE ) |
|
ibody = RPG_WEAPON_EMPTY; |
|
|
|
pev->body = ibody; |
|
} |
|
|
|
|
|
|
|
// animations idle |
|
|
|
if (m_flTimeWeaponIdle > gpGlobals->time) |
|
return; |
|
|
|
int iAnim; |
|
switch ( RANDOM_LONG( 0, 6 ) ) |
|
{ |
|
case 0: |
|
iAnim = RPG_FIDGET; |
|
m_flTimeWeaponIdle = gpGlobals->time + 15 / 4.0; |
|
break; |
|
|
|
default: |
|
iAnim = RPG_IDLE; |
|
m_flTimeWeaponIdle = gpGlobals->time + 15 / 3.0; |
|
break; |
|
} |
|
SendWeaponAnim( iAnim ); |
|
} |
|
|
|
|
|
|
|
|
|
void CRpg::UpdateEntityTarget( void ) |
|
{ |
|
if ( m_iMenuState & RPG_MENU_ACTIVE ) |
|
return; // le texte s'affiche et disparait selon la selection |
|
|
|
UTIL_MakeVectors( m_pPlayer->pev->v_angle ); |
|
Vector vecSrc = m_pPlayer->GetGunPosition( ); |
|
Vector vecAiming = gpGlobals->v_forward; |
|
|
|
TraceResult tr; |
|
UTIL_TraceLine ( vecSrc, vecSrc + vecAiming * 8192, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr ); //tracage du vecteur |
|
|
|
|
|
if ( tr.pHit && ( CBaseEntity :: Instance ( tr.pHit )) -> MyMonsterPointer() != NULL ) |
|
{ |
|
|
|
// si une entite est touchee et |
|
//que l'entit |
|
|
|
|
|
if ( m_pEntityTarget == NULL || ( m_pEntityTarget != NULL && ( m_pEntityTarget != (CBaseEntity::Instance(tr.pHit)) ) ) ) |
|
{ |
|
|
|
// si il n'y avait pas de cible, on en met une . On met en memoire l heure de reperage de la cible |
|
// une cible, mais pas la meme qu avant, ... |
|
|
|
m_pEntityTarget = CBaseEntity::Instance ( tr.pHit ); |
|
m_pEntityLocked = NULL; |
|
m_flLockTime = gpGlobals->time; |
|
UpdateCrosshair ( RPG_CROSSHAIR_PROCESS ); |
|
|
|
|
|
// son |
|
EMIT_SOUND ( ENT(pev), CHAN_BODY, "weapons/rpg_lock03.wav", 0.5, ATTN_NORM ); |
|
|
|
} |
|
|
|
else if ( ( m_pEntityTarget != NULL ) && ( m_pEntityTarget == (CBaseEntity::Instance(tr.pHit))) && ( gpGlobals->time - m_flLockTime > 1 ) ) |
|
{ |
|
// la meme cible pendant 1 sec , on verrouille |
|
|
|
|
|
m_pEntityLocked = m_pEntityTarget; |
|
UpdateCrosshair ( RPG_CROSSHAIR_LOCKED ); |
|
|
|
// son |
|
if ( m_flLastBip <= 0 || gpGlobals->time - m_flLastBip >= 0.1 ) |
|
{ |
|
EMIT_SOUND ( ENT(pev), CHAN_BODY, "weapons/rpg_lock03.wav", 0.5, ATTN_NORM ); |
|
m_flLastBip = gpGlobals->time; |
|
} |
|
} |
|
|
|
} |
|
|
|
else |
|
{ |
|
|
|
//si rien n est touche |
|
|
|
UpdateCrosshair ( RPG_CROSSHAIR_EMPTY ); |
|
m_pEntityTarget = m_pEntityLocked = NULL; |
|
m_flLockTime = 0; |
|
} |
|
|
|
} |
|
|
|
|
|
void CRpg :: PlayStateSound ( void ) |
|
{ |
|
/* |
|
if ( m_iAmmoType == AMMO_ROCKET ) |
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "sentences/hev_aim_on.wav", 0.9, ATTN_NORM ); |
|
|
|
else |
|
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "sentences/hev_aim_off.wav", 0.9, ATTN_NORM ); |
|
*/ |
|
} |
|
|
|
//------------------------------------------ |
|
// |
|
// messages au client |
|
// |
|
//------------------------------------------ |
|
|
|
void CRpg :: UpdateCrosshair ( int crosshair ) |
|
{ |
|
|
|
MESSAGE_BEGIN( MSG_ONE, gmsgRpgViseur, NULL, m_pPlayer->pev ); |
|
WRITE_BYTE( crosshair ); |
|
MESSAGE_END(); |
|
} |
|
|
|
|
|
void CRpg :: UpdateMenu ( void ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgRpgMenu, NULL, m_pPlayer->pev ); |
|
WRITE_BYTE( m_iMenuState ); |
|
WRITE_BYTE( m_iAmmoRocket ); |
|
WRITE_BYTE( m_iAmmoElectro ); |
|
WRITE_BYTE( m_iAmmoNuclear ); |
|
MESSAGE_END(); |
|
|
|
} |
|
|
|
|
|
//------------------------------------------ |
|
// |
|
// munitions |
|
// |
|
//------------------------------------------ |
|
|
|
void CRpg :: ItemTouch( CBaseEntity *pOther ) |
|
{ |
|
if ( pOther->IsPlayer() == FALSE ) |
|
{ |
|
return; |
|
} |
|
|
|
CBasePlayer *pPlayer = (CBasePlayer*)pOther; |
|
CBasePlayerItem *pItem; |
|
CRpg *pRpg = NULL; |
|
|
|
for ( int i = 0 ; i < MAX_ITEM_TYPES ; i++ ) |
|
{ |
|
pItem = pPlayer->m_rgpPlayerItems[ i ]; |
|
|
|
while (pItem) |
|
{ |
|
if ( !strcmp( "weapon_rpg", STRING( pItem->pev->classname ) ) ) |
|
{ |
|
pRpg = (CRpg*)pItem->GetWeaponPtr(); |
|
break; |
|
} |
|
pItem = pItem->m_pNext; |
|
} |
|
} |
|
|
|
if ( pRpg == NULL ) |
|
return; |
|
|
|
if ( pRpg->AddAmmo ( (CBasePlayerWeapon *) pRpg, AMMO_ROCKET, 1 ) ) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); |
|
UTIL_Remove( this ); |
|
} |
|
} |
|
|
|
int CRpg::ExtractAmmo( CBasePlayerWeapon *pWeapon ) |
|
{ |
|
// AddAmmo ( pWeapon, m_iAmmoType, 1 ); |
|
return 1; |
|
} |
|
|
|
int CRpg::ExtractClipAmmo( CBasePlayerWeapon *pWeapon ) |
|
{ |
|
// AddAmmo ( pWeapon, m_iAmmoType, 1 ); |
|
return 1; |
|
} |
|
|
|
BOOL CRpg ::AddAmmo ( CBasePlayerWeapon *pWeapon, int iAmmotype, int iNombre ) |
|
{ |
|
int *pType; |
|
CRpg *pRpg = (CRpg*) pWeapon; |
|
|
|
switch ( iAmmotype ) |
|
{ |
|
default: |
|
case AMMO_ROCKET: |
|
pType = &pRpg->m_iAmmoRocket; |
|
pRpg->m_iMenuState &= ~RPG_MENU_ROCKET_EMPTY; |
|
break; |
|
|
|
case AMMO_ELECTRO: |
|
pType = &pRpg->m_iAmmoElectro; |
|
pRpg->m_iMenuState &= ~RPG_MENU_ELECTRO_EMPTY; |
|
break; |
|
|
|
case AMMO_NUCLEAR: |
|
pType = &pRpg->m_iAmmoNuclear; |
|
pRpg->m_iMenuState &= ~RPG_MENU_NUCLEAR_EMPTY; |
|
break; |
|
|
|
} |
|
|
|
if ( pType[0] == RPG_MAX_AMMO ) |
|
return FALSE; |
|
|
|
pType[0] += iNombre; |
|
|
|
if ( m_pPlayer->m_pActiveItem == pWeapon ) |
|
{ |
|
pRpg->UpdateMenu(); |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
int CRpg :: GiveAmmo( int iAmount, char *szName, int iMax ) |
|
{ |
|
// AddAmmo ( this, m_iAmmoType, 1 ); |
|
return 1; |
|
} |
|
|
|
class CRpgAmmo : public CBasePlayerAmmo |
|
{ |
|
void Spawn( void ) |
|
{ |
|
Precache(); |
|
|
|
if ( FClassnameIs( pev, "ammo_rpgclip" ) ) |
|
SET_MODEL(ENT(pev), "models/w_rpgclip.mdl"); |
|
else if ( FClassnameIs( pev, "ammo_rpgelectroclip" ) ) |
|
SET_MODEL(ENT(pev), "models/w_rpgelectroclip.mdl"); |
|
else if ( FClassnameIs( pev, "ammo_rpgnuclearclip" ) ) |
|
SET_MODEL(ENT(pev), "models/w_rpgnuclearclip.mdl"); |
|
|
|
CBasePlayerAmmo::Spawn(); |
|
} |
|
void Precache( void ) |
|
{ |
|
PRECACHE_MODEL ("models/w_rpgclip.mdl"); |
|
PRECACHE_MODEL ("models/w_rpgelectroclip.mdl"); |
|
PRECACHE_MODEL ("models/w_rpgnuclearclip.mdl"); |
|
|
|
PRECACHE_SOUND( "items/9mmclip1.wav" ); |
|
} |
|
BOOL AddAmmo( CBaseEntity *pOther ) |
|
{ |
|
if ( pOther->IsPlayer() == 0 ) |
|
return FALSE; |
|
|
|
CBasePlayer *pPlayer = (CBasePlayer *) pOther; |
|
|
|
|
|
CBasePlayerItem *pItem; |
|
CRpg *pRpg = NULL; |
|
int i; |
|
int fin = 0; |
|
|
|
for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ ) |
|
{ |
|
pItem = pPlayer->m_rgpPlayerItems[ i ]; |
|
|
|
while (pItem) |
|
{ |
|
if ( !strcmp( "weapon_rpg"/*&pszItemName*/, STRING( pItem->pev->classname ) ) ) |
|
{ |
|
fin = 1; |
|
pRpg = (CRpg*)pItem->GetWeaponPtr(); |
|
} |
|
pItem = pItem->m_pNext; |
|
|
|
if ( fin ) |
|
break; |
|
} |
|
|
|
if ( fin ) |
|
break; |
|
} |
|
|
|
if ( pRpg == NULL ) |
|
return FALSE; |
|
|
|
int iAmmotype = 0; |
|
|
|
if ( FClassnameIs( pev, "ammo_rpgclip" ) ) |
|
iAmmotype = AMMO_ROCKET; |
|
else if ( FClassnameIs( pev, "ammo_rpgelectroclip" ) ) |
|
iAmmotype = AMMO_ELECTRO; |
|
else if ( FClassnameIs( pev, "ammo_rpgnuclearclip" ) ) |
|
iAmmotype = AMMO_NUCLEAR; |
|
else |
|
return FALSE; |
|
|
|
if ( pRpg->AddAmmo ( (CBasePlayerWeapon *) pRpg, iAmmotype, 1 ) == TRUE ) |
|
{ |
|
// accept |
|
|
|
switch ( iAmmotype ) |
|
{ |
|
default: |
|
case AMMO_ROCKET: |
|
break; |
|
case AMMO_ELECTRO: |
|
pRpg->m_pPlayer->TextAmmo( TA_ELECTROROCKET ); break; |
|
case AMMO_NUCLEAR: |
|
pRpg->m_pPlayer->TextAmmo( TA_NUCLEARROCKET ); break; |
|
} |
|
|
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); |
|
return TRUE; |
|
} |
|
|
|
else |
|
return FALSE; |
|
} |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( ammo_rpgclip, CRpgAmmo ) |
|
LINK_ENTITY_TO_CLASS( ammo_rpgelectroclip, CRpgAmmo ); |
|
LINK_ENTITY_TO_CLASS( ammo_rpgnuclearclip, CRpgAmmo ); |
|
|
|
|
|
//------------------------------------------ |
|
// |
|
// sauvegarde et restauration |
|
// |
|
//------------------------------------------ |
|
|
|
#if !CLIENT_DLL |
|
int CRpg::Save( CSave &save ) |
|
{ |
|
if ( !CBasePlayerWeapon::Save(save) ) |
|
return 0; |
|
|
|
return save.WriteFields( "CRpg", this, m_SaveData, ARRAYSIZE(m_SaveData) ); |
|
} |
|
|
|
int CRpg::Restore( CRestore &restore ) |
|
{ |
|
if ( !CBasePlayerWeapon::Restore(restore) ) |
|
return 0; |
|
|
|
int status = restore.ReadFields( "CRpg", this, m_SaveData, ARRAYSIZE(m_SaveData) ); |
|
|
|
//----------------------- |
|
|
|
m_bRpgUpdate = 1; // force le rafraichissement des donnees client |
|
|
|
//---------------------- |
|
return status; |
|
} |
|
#endif |