//------------------------------------------------- //- --- //- supergun.cpp --- //- --- //------------------------------------------------- // par Julien ----------------------- //------------------------------------------------- //- code de la mitrailleuse laser ----------- //------------------------------------------------- //---------------------------------------- // inclusions #include "extdll.h" #include "util.h" #include "cbase.h" #include "weapons.h" #include "monsters.h" #include "player.h" #include "gamerules.h" #include "effects.h" extern int gmsgClientDecal; enum supergun_e { SG_IDLE = 0, SG_SHOOT1, SG_BIGSHOOT, SG_DRAW, SG_RELOAD }; class CSuperGun : public CBasePlayerWeapon { public: /* int Save( CSave &save ); int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; */ void Spawn( void ); void Precache( void ); int iItemSlot( void ) { return 4; } int GetItemInfo(ItemInfo *p); int AddToPlayer( CBasePlayer *pPlayer ); BOOL Deploy( void ); void Holster( int skiplocal = 0 ); void PrimaryAttack( void ); void SecondaryAttack( void ); void Reload( void ); void WeaponIdle( void ); void Shoot ( int mode ); private: unsigned short m_usSG; }; LINK_ENTITY_TO_CLASS( weapon_supergun, CSuperGun ); /* TYPEDESCRIPTION CGauss::m_SaveData[] = { DEFINE_FIELD( CGauss, m_fInAttack, FIELD_INTEGER ), DEFINE_FIELD( CGauss, m_flStartCharge, FIELD_TIME ), DEFINE_FIELD( CGauss, m_flPlayAftershock, FIELD_TIME ), DEFINE_FIELD( CGauss, m_flNextAmmoBurn, FIELD_TIME ), DEFINE_FIELD( CGauss, m_fPrimaryFire, FIELD_BOOLEAN ), }; IMPLEMENT_SAVERESTORE( CGauss, CBasePlayerWeapon ); */ //-------------------------------------------------------------------------- class CSGBall : public CBaseMonster { public : void Spawn( void ); void Precache( void ); void EXPORT AnimateThink( void ); void EXPORT ExplodeTouch( CBaseEntity *pOther ); int Classify ( void ); static CSGBall *CreateSGBall( Vector vecOrigin, Vector vecAngles, entvars_s *pevOwner ); int m_iSprite; }; LINK_ENTITY_TO_CLASS( sg_ball, CSGBall ); CSGBall *CSGBall :: CreateSGBall ( Vector vecOrigin, Vector vecAngles, entvars_s *pevOwner ) { CSGBall *pBall = GetClassPtr( (CSGBall *)NULL ); UTIL_MakeAimVectors ( vecAngles ); float x, y, z; do { x = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); y = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); z = x*x+y*y; } while (z > 1); Vector vecDir = gpGlobals->v_forward + x * VECTOR_CONE_6DEGREES.x * gpGlobals->v_right + y * VECTOR_CONE_6DEGREES.y * gpGlobals->v_up; pBall->pev->angles = UTIL_VecToAngles ( vecDir.Normalize() ); UTIL_SetOrigin( pBall->pev, vecOrigin ); pBall->pev->owner = ENT ( pevOwner ); pBall->Spawn(); pBall->SetTouch( &CSGBall::ExplodeTouch ); return pBall; } void CSGBall :: Spawn( void ) { Precache( ); // motor pev->movetype = MOVETYPE_FLY; pev->solid = SOLID_BBOX; pev->classname = MAKE_STRING("sg_ball"); SET_MODEL(ENT(pev), "sprites/cnt1.spr"); pev->rendermode = kRenderTransAdd; pev->rendercolor.x = 255; pev->rendercolor.y = 255; pev->rendercolor.z = 255; pev->renderamt = 190; pev->scale = 0.1; UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0)); UTIL_SetOrigin( pev, pev->origin ); SetThink( &CSGBall::AnimateThink ); SetTouch( &CSGBall::ExplodeTouch ); pev->dmgtime = gpGlobals->time; // keep track of when ball spawned pev->nextthink = gpGlobals->time + 0.1; UTIL_MakeVectors ( pev->angles ); pev->velocity = gpGlobals->v_forward * 1700; m_flFieldOfView = -1; m_hEnemy = 0; } int CSGBall::Classify ( void ) { return CLASS_PLAYER_BIOWEAPON; } void CSGBall :: Precache( void ) { PRECACHE_MODEL("sprites/cnt1.spr"); PRECACHE_MODEL("sprites/xspark1.spr"); PRECACHE_MODEL("sprites/xspark4.spr"); PRECACHE_SOUND("debris/zap4.wav"); PRECACHE_SOUND("weapons/electro4.wav"); m_iSprite = PRECACHE_MODEL("sprites/cnt1.spr"); } void CSGBall :: AnimateThink( void ) { pev->nextthink = gpGlobals->time + 0.05; // sprite pev->frame = ((int)pev->frame + 1) % 5; float delta = gpGlobals->time - pev->dmgtime; if ( delta > 5 || pev->velocity.Length() < 10) { SetTouch( NULL ); UTIL_Remove( this ); } // train if ( delta > 0 && delta < 0.9 ) { CSprite *pTrail = CSprite::SpriteCreate ( "sprites/cnt1.spr", pev->origin, TRUE ); // pTrail->AnimateAndDie ( 7 ); pTrail->AnimateAndDie ( 0.2 ); pTrail->SetScale ( 0.07 ); pTrail->SetTransparency ( kRenderTransAdd, 230, 255, 230, 60, kRenderFxNone ); pTrail->Expand ( pTrail->pev->scale, 120 ); } // ennemi if ( m_hEnemy == 0 ) { Look( 600 ); m_hEnemy = BestVisibleEnemy( ); } if ( m_hEnemy != 0 && FVisible( m_hEnemy )) { Vector vecDirToEnemy = ( m_hEnemy->BodyTarget( pev->origin ) - pev->origin ).Normalize(); Vector angEnnemy = UTIL_VecToAngles(vecDirToEnemy); Vector angBall = UTIL_VecToAngles(pev->velocity); float difX = UTIL_AngleDiff( angEnnemy.x, angBall.x ); float difY = UTIL_AngleDiff( angEnnemy.y, angBall.y ); if ( fabs ( difX ) < 15 && fabs ( difY ) < 15 ) { pev->velocity = vecDirToEnemy * pev->velocity.Length(); } } else { m_hEnemy = 0; } } void CSGBall::ExplodeTouch( CBaseEntity *pOther ) { // truc affreux pour creer une particule a travers ce message pour les decals TraceResult trace = UTIL_GetGlobalTrace( ); Vector vecNorm = trace.vecPlaneNormal.Normalize(); MESSAGE_BEGIN( MSG_ALL, gmsgClientDecal ); WRITE_COORD( trace.vecEndPos.x ); // xyz source WRITE_COORD( trace.vecEndPos.y ); WRITE_COORD( trace.vecEndPos.z ); WRITE_COORD( vecNorm.x ); // xyz norme WRITE_COORD( vecNorm.y ); WRITE_COORD( vecNorm.z ); WRITE_CHAR ( 'a' ); // type de texture WRITE_BYTE ( 5 ); // 4 == electro-rocket MESSAGE_END(); if (pOther->pev->takedamage) { if ( pOther->pev != VARS ( pev->owner ) ) { TraceResult tr = UTIL_GetGlobalTrace( ); ClearMultiDamage( ); pOther->TraceAttack(pev, gSkillData.plrDmgSupergun, pev->velocity.Normalize(), &tr, DMG_ENERGYBEAM ); ApplyMultiDamage( pev, pev ); UTIL_EmitAmbientSound( ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.3, ATTN_NORM, 0, RANDOM_LONG( 90, 99 ) ); } } UTIL_Remove( this ); } //-------------------------------------------------------------------------- // // SuperGun // //-------------------------------------------------------------------------- void CSuperGun::Spawn( ) { Precache( ); m_iId = WEAPON_SUPERGUN; SET_MODEL(ENT(pev), "models/w_supergun.mdl"); m_iDefaultAmmo = SUPERGUN_DEFAULT_GIVE; FallInit();// get ready to fall down. } void CSuperGun::Precache( void ) { PRECACHE_MODEL("models/w_supergun.mdl"); PRECACHE_MODEL("models/v_supergun.mdl"); PRECACHE_MODEL("models/p_gauss.mdl"); // PRECACHE_MODEL("sprites/animglow01.spr"); PRECACHE_MODEL("sprites/blueflare1.spr"); PRECACHE_SOUND("items/9mmclip1.wav"); PRECACHE_SOUND("turret/tu_fire1.wav"); PRECACHE_SOUND("weapons/gauss2.wav"); PRECACHE_SOUND("debris/beamstart14.wav"); m_usSG = PRECACHE_EVENT( 1, "events/supergun.sc" ); UTIL_PrecacheOther ( "sg_ball" ); } int CSuperGun::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_SUPERGUN ); return TRUE; } return FALSE; } int CSuperGun::GetItemInfo(ItemInfo *p) { p->pszName = STRING(pev->classname); p->pszAmmo1 = "chewinggum"; p->iMaxAmmo1 = SUPERGUN_MAX_CARRY; p->pszAmmo2 = NULL; p->iMaxAmmo2 = -1; p->iMaxClip = SUPERGUN_MAX_CLIP; p->iSlot = 3; p->iPosition = 3; p->iId = m_iId = WEAPON_SUPERGUN; p->iFlags = 0; p->iWeight = SUPERGUN_WEIGHT; return 1; } BOOL CSuperGun::Deploy( ) { BOOL bResult = DefaultDeploy( "models/v_supergun.mdl", "models/p_gauss.mdl", SG_DRAW, "supergun" ); m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 2, 5 ); return bResult; } void CSuperGun::Holster( int skiplocal ) { m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; SendWeaponAnim( SG_DRAW ); EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); } void CSuperGun :: Reload ( void ) { DefaultReload( SUPERGUN_MAX_CLIP, SG_RELOAD, 69 / 25 ); int iskin = 0; PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usSG, 1, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iskin, 0, 0, 0 ); } void CSuperGun::PrimaryAttack() { // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->time + 0.15; return; } // enflamme le gaz if ( m_pPlayer->IsInGaz() == TRUE ) m_pPlayer->m_bFireInGaz = TRUE; if ( m_iClip < 1 ) { PlayEmptySound( ); m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; return; } m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_iClip--; m_pPlayer->Gunflash (); if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); // flash CSprite *pMuzzle = CSprite::SpriteCreate ( "sprites/blueflare1.spr"/*"sprites/animglow01.spr"*/, Vector(0,0,0), TRUE ); pMuzzle->SetAttachment ( m_pPlayer->edict(), 1 ); pMuzzle->SetScale ( 0.3 ); pMuzzle->SetTransparency ( kRenderTransAdd, 128, 128, 220, 250, kRenderFxNone ); // pMuzzle->pev->frame = RANDOM_LONG(3,6); pMuzzle->SetThink ( &CBaseEntity::SUB_Remove ); pMuzzle->pev->nextthink = gpGlobals->time + 0.075; SendWeaponAnim( SG_SHOOT1 ); Shoot ( 0 ); int iskin = (int)( (SUPERGUN_MAX_CLIP - m_iClip) * 10 / SUPERGUN_MAX_CLIP ); PLAYBACK_EVENT_FULL( 0, m_pPlayer->edict(), m_usSG, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iskin, 1, 0, 0 ); m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 1,4 ); m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.1; } void CSuperGun::SecondaryAttack() { // don't fire underwater if (m_pPlayer->pev->waterlevel == 3) { PlayEmptySound( ); m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->time + 0.15; return; } // enflamme le gaz if ( m_pPlayer->IsInGaz() == TRUE ) m_pPlayer->m_bFireInGaz = TRUE; if ( m_iClip < 1 ) { PlayEmptySound( ); m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; return; } int iProjectiles = Q_min ( m_iClip, 8 ); // n'en tire pas plus qu'il n'en a ... m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_iClip -= iProjectiles; m_pPlayer->Gunflash (); if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); // flash CSprite *pMuzzle = CSprite::SpriteCreate ( "sprites/blueflare1.spr", Vector(0,0,0), TRUE ); pMuzzle->SetAttachment ( m_pPlayer->edict(), 1 ); pMuzzle->SetScale ( 0.3 ); pMuzzle->SetTransparency ( kRenderTransAdd, 128, 128, 220, 250, kRenderFxNone ); pMuzzle->SetThink ( &CBaseEntity::SUB_Remove ); pMuzzle->pev->nextthink = gpGlobals->time + 0.2; SendWeaponAnim( SG_BIGSHOOT ); // sons EMIT_SOUND ( m_pPlayer->edict(), CHAN_WEAPON, "weapons/gauss2.wav", 1.0, ATTN_NORM ); EMIT_SOUND ( m_pPlayer->edict(), CHAN_ITEM, "debris/beamstart14.wav", 1.0, ATTN_NORM ); UTIL_MakeVectors ( m_pPlayer->pev->v_angle ); Vector Point [8]; Point [0] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 8 - gpGlobals->v_up * 8; Point [1] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 10 - gpGlobals->v_up * 9; Point [2] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 11 - gpGlobals->v_up * 11; Point [3] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 10 - gpGlobals->v_up * 13; Point [4] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 8 - gpGlobals->v_up * 14; Point [5] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 6 - gpGlobals->v_up * 13; Point [6] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 5 - gpGlobals->v_up * 11; Point [7] = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 6 - gpGlobals->v_up * 9; for ( int i=0; ipev->v_angle, m_pPlayer->pev ); } m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 3,6 ); m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 31 / 20; } void CSuperGun :: Shoot ( int mode ) { EMIT_SOUND ( m_pPlayer->edict(), CHAN_WEAPON, "turret/tu_fire1.wav", 1.0, ATTN_NORM ); //CBaseMonster *pBall = (CBaseMonster*)Create( "controller_energy_ball", m_pPlayer->GetGunPosition(), m_pPlayer->pev->v_angle, edict() ); UTIL_MakeVectors ( m_pPlayer->pev->v_angle ); CSGBall :: CreateSGBall ( m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 15 + gpGlobals->v_right * 8 - gpGlobals->v_up * 8, m_pPlayer->pev->v_angle, m_pPlayer->pev ); } void CSuperGun::WeaponIdle( void ) { ResetEmptySound( ); if (m_flTimeWeaponIdle > gpGlobals->time) return; SendWeaponAnim( SG_IDLE ); m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); } class CSuperGunAmmo : public CBasePlayerAmmo { void Spawn( void ) { Precache( ); SET_MODEL(ENT(pev), "models/w_supergunammo.mdl"); CBasePlayerAmmo::Spawn( ); } void Precache( void ) { PRECACHE_MODEL ("models/w_supergunammo.mdl"); PRECACHE_SOUND("items/9mmclip1.wav"); } BOOL AddAmmo( CBaseEntity *pOther ) { if (pOther->GiveAmmo( AMMO_SUPERGUNCLIPGIVE, "chewinggum", SUPERGUN_MAX_CARRY ) != -1) { EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); return TRUE; } return FALSE; } }; LINK_ENTITY_TO_CLASS( ammo_supergun, CSuperGunAmmo );