forked from FWGS/Paranoia2
319 lines
8.0 KiB
C++
319 lines
8.0 KiB
C++
/***************************************
|
||
*
|
||
* Writen by BUzer for Half-Life: Paranoia modification
|
||
*
|
||
* Static machineguns code
|
||
*
|
||
****************************************/
|
||
|
||
#include "extdll.h"
|
||
#include "util.h"
|
||
#include "cbase.h"
|
||
#include "effects.h"
|
||
#include "weapons.h"
|
||
#include "explode.h"
|
||
#include "monsters.h"
|
||
#include "movewith.h"
|
||
#include "animation.h"
|
||
|
||
#include "player.h"
|
||
|
||
extern int gmsgSpecTank;
|
||
|
||
|
||
class CFuncMachinegun : public CBaseAnimating
|
||
{
|
||
public:
|
||
void Spawn( void );
|
||
void Precache( void );
|
||
void KeyValue( KeyValueData *pkvd );
|
||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||
virtual int ObjectCaps( void ) { return FCAP_IMPULSE_USE; }
|
||
BOOL OnControls( entvars_t *pevTest );
|
||
void PostFrame( CBaseEntity *pActivator );
|
||
void UpdateClientData( CBasePlayer *client );
|
||
|
||
virtual int Save( CSave &save );
|
||
virtual int Restore( CRestore &restore );
|
||
static TYPEDESCRIPTION m_SaveData[];
|
||
|
||
// short m_usEvent;
|
||
float m_flPointHeight;
|
||
float m_flDistUp, m_flDistFwd;
|
||
// float m_flConeHor, m_flConeVer;
|
||
float m_flNextAttack;
|
||
float m_fireRate;
|
||
float m_flDamage;
|
||
// Vector savedPlayerAngles;
|
||
int m_iShouldUpdate;
|
||
// float m_flLastAnimTime;
|
||
int m_iAmmo;
|
||
};
|
||
|
||
LINK_ENTITY_TO_CLASS( func_machinegun, CFuncMachinegun );
|
||
|
||
TYPEDESCRIPTION CFuncMachinegun::m_SaveData[] =
|
||
{
|
||
DEFINE_FIELD( CFuncMachinegun, m_flPointHeight, FIELD_FLOAT ),
|
||
DEFINE_FIELD( CFuncMachinegun, m_flDistUp, FIELD_FLOAT ),
|
||
DEFINE_FIELD( CFuncMachinegun, m_flDistFwd, FIELD_FLOAT ),
|
||
// DEFINE_FIELD( CFuncMachinegun, m_flConeHor, FIELD_FLOAT ),
|
||
// DEFINE_FIELD( CFuncMachinegun, m_flConeVer, FIELD_FLOAT ),
|
||
DEFINE_FIELD( CFuncMachinegun, m_flNextAttack, FIELD_TIME ),
|
||
DEFINE_FIELD( CFuncMachinegun, m_fireRate, FIELD_FLOAT ),
|
||
DEFINE_FIELD( CFuncMachinegun, m_flDamage, FIELD_FLOAT ),
|
||
// DEFINE_FIELD( CFuncMachinegun, savedPlayerAngles, FIELD_VECTOR ),
|
||
// DEFINE_FIELD( CFuncMachinegun, m_flLastAnimTime, FIELD_TIME ),
|
||
DEFINE_FIELD( CFuncMachinegun, m_iAmmo, FIELD_INTEGER ),
|
||
};
|
||
|
||
IMPLEMENT_SAVERESTORE( CFuncMachinegun, CBaseAnimating );
|
||
|
||
|
||
void CFuncMachinegun::Precache()
|
||
{
|
||
PRECACHE_MODEL( (char *)STRING(pev->model) );
|
||
PRECACHE_MODEL ("models/shell.mdl");
|
||
|
||
pev->sequence = 0;
|
||
pev->frame = 0;
|
||
pev->framerate = 1;
|
||
ResetSequenceInfo();
|
||
m_fSequenceLoops = TRUE;
|
||
|
||
m_iShouldUpdate = 1;
|
||
}
|
||
|
||
|
||
void CFuncMachinegun::KeyValue( KeyValueData *pkvd )
|
||
{
|
||
if (FStrEq(pkvd->szKeyName, "baseheight"))
|
||
{
|
||
m_flPointHeight = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
else if (FStrEq(pkvd->szKeyName, "distfwd"))
|
||
{
|
||
m_flDistFwd = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
else if (FStrEq(pkvd->szKeyName, "distup"))
|
||
{
|
||
m_flDistUp = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
/* else if (FStrEq(pkvd->szKeyName, "conehor"))
|
||
{
|
||
m_flConeHor = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
else if (FStrEq(pkvd->szKeyName, "conever"))
|
||
{
|
||
m_flConeVer = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}*/
|
||
else if (FStrEq(pkvd->szKeyName, "firerate"))
|
||
{
|
||
m_fireRate = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
else if (FStrEq(pkvd->szKeyName, "damage"))
|
||
{
|
||
m_flDamage = atof(pkvd->szValue);
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
else if (FStrEq(pkvd->szKeyName, "ammo"))
|
||
{
|
||
m_iAmmo = atoi(pkvd->szValue);
|
||
if (m_iAmmo > 999) m_iAmmo = 999;
|
||
if (m_iAmmo < -1) m_iAmmo = -1;
|
||
pkvd->fHandled = TRUE;
|
||
}
|
||
else
|
||
CBaseAnimating::KeyValue( pkvd );
|
||
}
|
||
|
||
|
||
void CFuncMachinegun::Spawn()
|
||
{
|
||
Precache();
|
||
|
||
pev->movetype = MOVETYPE_NONE;
|
||
pev->solid = SOLID_BBOX;
|
||
pev->angles.x = 0; // remove pitch
|
||
// m_flLastAnimTime = gpGlobals->time;
|
||
pev->renderfx = 51; // <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
SET_MODEL( ENT(pev), STRING(pev->model) );
|
||
UTIL_SetSize( pev, Vector(-25,-25,0), Vector(25,25,60));
|
||
|
||
ResetSequenceInfo();
|
||
m_fSequenceLoops = TRUE;
|
||
|
||
InitBoneControllers();
|
||
}
|
||
|
||
|
||
BOOL CFuncMachinegun::OnControls( entvars_t *pevTest )
|
||
{
|
||
Vector vecToPlayer = pevTest->origin - pev->origin;
|
||
vecToPlayer.z = 0;
|
||
|
||
if ( vecToPlayer.Length() > 50 )
|
||
return FALSE;
|
||
|
||
UTIL_MakeVectors(pev->angles);
|
||
vecToPlayer = vecToPlayer.Normalize();
|
||
|
||
if (DotProduct(vecToPlayer, gpGlobals->v_forward) > -0.7)
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void CFuncMachinegun::PostFrame( CBaseEntity *pActivator )
|
||
{
|
||
Vector plAngles = pActivator->pev->angles;
|
||
while (plAngles.y < 0) plAngles.y += 360;
|
||
|
||
float yawAngle = plAngles.y - pev->angles.y;
|
||
float pitchAngle = pActivator->pev->angles.x * -3;
|
||
SetBoneController( 0, yawAngle );
|
||
SetBoneController( 1, pitchAngle );
|
||
|
||
StudioFrameAdvance(); // ^%&*(#%$%^@# !!!!
|
||
|
||
// return to idle after fire anim
|
||
if (m_fSequenceFinished)
|
||
{
|
||
pev->sequence = 0;
|
||
pev->frame = 0;
|
||
ResetSequenceInfo();
|
||
// ALERT(at_console, "return to idle\n");
|
||
m_fSequenceLoops = TRUE;
|
||
}
|
||
|
||
if ( gpGlobals->time < m_flNextAttack )
|
||
return;
|
||
|
||
// ALERT(at_console, "current ammo: %d\n", m_iAmmo);
|
||
|
||
if ( pActivator->pev->button & IN_ATTACK && (m_iAmmo > 0 || m_iAmmo == -1))
|
||
{
|
||
// fire
|
||
Vector vecForward, vecSrc, vecAngles;
|
||
vecAngles = pActivator->pev->angles;
|
||
vecAngles.x = vecAngles.x * -3; // invert anf scale pitch
|
||
UTIL_MakeVectorsPrivate( vecAngles, vecForward, NULL, NULL );
|
||
GetAttachment(0, vecSrc, vecAngles);
|
||
|
||
pev->sequence = 1; // sounds, muzzleflashes, and shells will go by anim event
|
||
pev->frame = 0;
|
||
ResetSequenceInfo();
|
||
m_fSequenceLoops = FALSE;
|
||
|
||
if( !m_flDamage ) m_flDamage = gSkillData.monDmg12MM;
|
||
FireBullets( 1, vecSrc, vecForward, Vector( 0, 0, 0 ), 4096, BULLET_NORMAL, m_flDamage, pActivator->pev );
|
||
if (m_iAmmo > 0) m_iAmmo--;
|
||
|
||
// update ammo counter
|
||
MESSAGE_BEGIN( MSG_ONE, gmsgSpecTank, NULL, pActivator->pev );
|
||
WRITE_BYTE( 2 ); // ammo update
|
||
WRITE_LONG(m_iAmmo);
|
||
MESSAGE_END();
|
||
|
||
// HACKHACK -- make some noise (that the AI can hear)
|
||
if ( pActivator->IsPlayer() )
|
||
((CBasePlayer *)pActivator)->m_iWeaponVolume = LOUD_GUN_VOLUME;
|
||
|
||
m_flNextAttack = gpGlobals->time + ( 1.0f / m_fireRate );
|
||
}
|
||
|
||
// ALERT(at_console, "current sequence: %d\n", pev->sequence);
|
||
}
|
||
|
||
|
||
void CFuncMachinegun::UpdateClientData( CBasePlayer *client )
|
||
{
|
||
if (m_iShouldUpdate)
|
||
{
|
||
Vector vecPoint = pev->origin + Vector(0, 0, m_flPointHeight);
|
||
float coneHor = GetControllerBound( 0 );
|
||
float coneVer = GetControllerBound( 1 );
|
||
|
||
MESSAGE_BEGIN( MSG_ONE, gmsgSpecTank, NULL, client->pev );
|
||
WRITE_BYTE( 1 ); // tank is on
|
||
WRITE_COORD(vecPoint.x);
|
||
WRITE_COORD(vecPoint.y);
|
||
WRITE_COORD(vecPoint.z);
|
||
WRITE_COORD(pev->angles.y); // write default yaw
|
||
WRITE_COORD(coneHor); // write cone
|
||
WRITE_COORD(coneVer); //
|
||
WRITE_COORD(m_flDistFwd);
|
||
WRITE_COORD(m_flDistUp);
|
||
WRITE_LONG(m_iAmmo);
|
||
MESSAGE_END();
|
||
|
||
m_iShouldUpdate = 0;
|
||
}
|
||
}
|
||
|
||
void CFuncMachinegun::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||
{
|
||
if (!pActivator->IsPlayer())
|
||
{
|
||
ALERT(at_console, "non player activating func_machinegun!\n");
|
||
return;
|
||
}
|
||
|
||
if (useType == USE_SET && value == 2) // called by playerthink, update position
|
||
{
|
||
PostFrame( pActivator );
|
||
}
|
||
else if (useType == USE_SET && value == 3) // update client data
|
||
{
|
||
UpdateClientData( (CBasePlayer*)pActivator );
|
||
}
|
||
else if (useType == USE_OFF) // turn off
|
||
{
|
||
CBasePlayer *player = (CBasePlayer *)pActivator;
|
||
// player->pev->angles = savedPlayerAngles;
|
||
MESSAGE_BEGIN( MSG_ONE, gmsgSpecTank, NULL, player->pev );
|
||
WRITE_BYTE( 0 ); // tank is off
|
||
MESSAGE_END();
|
||
|
||
pev->sequence = 0;
|
||
pev->frame = 0;
|
||
ResetSequenceInfo();
|
||
m_fSequenceLoops = TRUE;
|
||
|
||
if ( player->m_pActiveItem )
|
||
player->m_pActiveItem->Deploy();
|
||
|
||
player->m_iHideHUD &= ~HIDEHUD_WEAPONS;
|
||
}
|
||
else // turn on
|
||
{
|
||
// is player in valid zone
|
||
if ( OnControls(pActivator->pev) )
|
||
{
|
||
CBasePlayer *player = (CBasePlayer *)pActivator;
|
||
player->m_pSpecTank = this;
|
||
m_iShouldUpdate = 1;
|
||
// savedPlayerAngles = player->pev->angles;
|
||
// player->pev->angles = pev->angles;
|
||
player->m_iHideHUD |= HIDEHUD_WEAPONS;
|
||
|
||
if ( player->m_pActiveItem )
|
||
{
|
||
player->m_pActiveItem->Holster( true );
|
||
player->pev->weaponmodel = 0;
|
||
player->pev->viewmodel = 0;
|
||
}
|
||
}
|
||
// else
|
||
// ALERT(at_console, "player is not in valid zone\n");
|
||
}
|
||
}
|