This member has provided no bio about themself...

Report article RSS Feed ScrGold/Coding: HL1 Flamethrower Experiement

Posted by PanSartre on Feb 22nd, 2013

weapon.h
//=========================================================
// Flamethrower
//=========================================================
class CFlamethrower : public CBasePlayerWeapon
{
public:

void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 2; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );
void PrimaryAttack( void );

void StartThrow (void);
void Throw (void);
void StopThrow(void);

BOOL Deploy( void );
void Holster( int skiplocal = 0 );
void WeaponIdle( void );
void UpdateTrace( void );

float m_flThrowTime;
int m_iStartThrow;
int m_iThrowCount;
int m_iFlameRange;
//int m_iFlameSprite;

virtual BOOL UseDecrement( void )
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}

private:
unsigned short m_usThrowerFire;
unsigned short m_usThrowerStop;
unsigned short m_usThrowerFlame;
};

//=========================================================
// Flamethrower FireBall
//=========================================================
class CFireBall : public CBaseMonster
{
public:
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[]; //weapon.cpp
void Spawn( void );
void Precache( void );
void EXPORT AnimateThink( void );
void Smoke( void );
void Damage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType );
void EXPORT TouchThink( CBaseEntity *pOther );
static CFireBall *CreateFireBall( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CFlamethrower *pLauncher );

private:
int m_iFlametrail;
int m_maxFrame;
float m_flFlameTime;
CFlamethrower *m_pLauncher;// pointer back to the launcher that fired me. MAYBE NOT NEEDED
};

flamethrower.cpp
//=========================================================
// Flamethrower
//=========================================================
#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 "decals.h"
#include "effects.h"
#include "customentity.h"

#define FIRE_BALL_SPRITE "sprites/fireball01.spr" //"sprites/flameball.spr"
#define FIRE_BALL_SPRITE2 "sprites/fireball02.spr" //"sprites/flameball.spr"
#define FIRE_BALL_SPRITE3 "sprites/fireball03.spr" //"sprites/flameball.spr"
#define FIRE_BEAM_SPRITE "sprites/xbeam3.spr"
extern DLL_GLOBAL short g_sModelIndexSteam;
//#define SMOKE_BALL_SPRITE "sprites/stmbal1.spr"

enum flamethrower_e {
FLAME_IDLE1 = 0,
FLAME_START_SHOOT,
FLAME_SHOOT,
FLAME_STOP_SHOOT,
FLAME_DRAW,
FLAME_HOLSTER, //no animation
};

//EGON ANIMATION

//enum flamethrower_e {
// FLAME_IDLE1 = 0,
// FLAME_FIDGET,
// FLAME_FIREON,
// FLAME_FIRECYCLE,
// FLAME_FIREOFF,
// FLAME_FIRE1, //no animation
// FLAME_FIRE2, //no animation
// FLAME_FIRE3,
// FLAME_FIRE4,
// FLAME_DRAW,
// FLAME_HOLSTER
//};

#ifndef CLIENT_DLL
//=========================================================
// Flamethrower FlameBall
//=========================================================

LINK_ENTITY_TO_CLASS( ft_fireball, CFireBall );

void CFireBall :: Spawn( void )
{
Precache( );
pev->classname = MAKE_STRING("ft_fireball");
pev->movetype = MOVETYPE_FLY; //MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
//pev->effects = EF_BRIGHTLIGHT; //only a test

switch ( RANDOM_LONG( 0, 2 ) )
{
case 0:
SET_MODEL(ENT(pev), FIRE_BALL_SPRITE);
break;
case 1:
SET_MODEL(ENT(pev), FIRE_BALL_SPRITE2);
break;
case 2:
SET_MODEL(ENT(pev), FIRE_BALL_SPRITE3);
break;
}

pev->rendermode = kRenderTransAdd;
pev->renderamt = 255;
pev->avelocity.z = RANDOM_FLOAT(-180,180);
pev->scale = RANDOM_FLOAT( 0.10, 0.15); //0.30;
pev->frame = 0;

// flame trail
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMFOLLOW );
WRITE_SHORT(entindex()); // entity
WRITE_SHORT(m_iFlametrail ); // model
WRITE_BYTE( 2 ); // life
WRITE_BYTE( 10 ); // width
WRITE_BYTE( 205 ); // r, g, b
WRITE_BYTE( 147 ); // r, g, b
WRITE_BYTE( 49 ); // r, g, b
WRITE_BYTE( 225 ); // brightness
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)

UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));

//pev->velocity = gpGlobals->v_forward * RANDOM_FLOAT( 600, 750); //700;
m_flFlameTime = gpGlobals->time;

m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
pev->dmg = gSkillData.plrDmgFlame;

}

//test
void CFireBall :: Damage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType )
{
CBaseEntity *pEntity = NULL;
TraceResult tr;
float flAdjustedDamage, falloff;
Vector vecSpot;

if ( flRadius )
falloff = flDamage / flRadius;
else
falloff = 1.0;

int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);

vecSrc.z += 1;// in case grenade is lying on the ground

if ( !pevAttacker )
pevAttacker = pevInflictor;

// iterate on all entities in the vicinity.
while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
{
if ( pEntity->pev->takedamage != DAMAGE_NO )
{
// UNDONE: this should check a damage mask, not an ignore
if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
{// houndeyes don't hurt other houndeyes with their attack
continue;
}

// blast's don't tavel into or out of water
if (bInWater && pEntity->pev->waterlevel == 0)
continue;
if (!bInWater && pEntity->pev->waterlevel == 3)
continue;

vecSpot = pEntity->BodyTarget( vecSrc );

UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr );

if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
{// the explosion can 'see' this entity, so hurt them!
if (tr.fStartSolid)
{
// if we're stuck inside them, fixup the position and distance
tr.vecEndPos = vecSrc;
tr.flFraction = 0.0;
}

// decrease damage for an ent that's farther from the bomb.
flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff;
flAdjustedDamage = flDamage - flAdjustedDamage;

if ( flAdjustedDamage < 0 )
{
flAdjustedDamage = 0;
}

// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
if (tr.flFraction != 1.0)
{
ClearMultiDamage( );
pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType );
ApplyMultiDamage( pevInflictor, pevAttacker );
}
else
{
pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
}
}
}
}
}

void CFireBall :: AnimateThink( void )
{
if( UTIL_PointContents(pev->origin) == CONTENTS_WATER )
{
Smoke();
SetThink ( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time;
}

//if( UTIL_PointContents(pev->origin) == CONTENTS_SLIME || CONTENTS_LAVA )
//{
// pev->velocity = 0;
//}

pev->nextthink = gpGlobals->time + 0.05;
pev->velocity = pev->velocity * 0.97;
pev->scale = pev->scale += 0.04;

//CBaseEntity *pHurt = CheckTraceHullAttack( 32, 1, DMG_BURN ); //works, but not perfect
entvars_t *pevOwner;
if ( pev->owner )
pevOwner = VARS( pev->owner );
else
pevOwner = NULL;

pev->owner = NULL; // can't traceline attack owner if this is set

if ( gpGlobals->time - m_flFlameTime >= 0.1 )
{
Damage( pev->origin, pev, pev, 1, pev->scale * 64, CLASS_NONE, DMG_BURN );
}

//if ( RANDOM_FLOAT( 0.0 , 0.6 ) + ( gpGlobals->time - m_flFlameTime ) >= 0.9 )
//{
// Smoke();
//}

if ( pev->frame++ || gpGlobals->time - m_flFlameTime > 0.90)
{
if ( pev->frame > m_maxFrame || gpGlobals->time - m_flFlameTime > 0.90 ) //pev->frame > m_maxFrame ||
{
pev->frame = m_maxFrame;
SetThink ( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
}

if ( gpGlobals->time - m_flFlameTime >= 0.3 )
{
//pev->velocity = pev->velocity / RANDOM_FLOAT( 2,3);
if ( pev->movetype != MOVETYPE_TOSS )
{
pev->movetype = MOVETYPE_TOSS;
pev->gravity = RANDOM_FLOAT( 0.4 , 0.5 );
//pev->gravity = RANDOM_FLOAT(-4,-1);
}

}
}

void CFireBall :: Smoke( void )
{
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_SMOKE );
WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -16, 16 ));
WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -16, 16 ));
WRITE_COORD( pev->origin.z + RANDOM_FLOAT( 32, 16 ));
WRITE_SHORT( g_sModelIndexSteam );
WRITE_BYTE( RANDOM_FLOAT( 32 , 36 ));
WRITE_BYTE( 35 ); // framerate
MESSAGE_END();
}

void CFireBall :: Precache( void )
{
PRECACHE_MODEL( FIRE_BALL_SPRITE );
PRECACHE_MODEL( FIRE_BALL_SPRITE2 );
PRECACHE_MODEL( FIRE_BALL_SPRITE3 );
m_iFlametrail = PRECACHE_MODEL("sprites/smoke.spr");
}

CFireBall *CFireBall::CreateFireBall( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CFlamethrower *pLauncher )
{
CFireBall *pFireBall = GetClassPtr( (CFireBall *)NULL );

UTIL_SetOrigin( pFireBall->pev, vecOrigin );
pFireBall->pev->angles = vecAngles;
pFireBall->Spawn();
pFireBall->SetTouch( &CFireBall :: TouchThink );
pFireBall->m_pLauncher = pLauncher;// remember what RPG fired me.
pFireBall->pev->owner = pOwner->edict();
pFireBall->pev->nextthink = gpGlobals->time;
pFireBall->SetThink( &CFireBall::AnimateThink );

return pFireBall;
}

void CFireBall :: TouchThink ( CBaseEntity *pOther )
{
TraceResult tr;

if ( !pOther->pev->takedamage )
{
return;
}
else
{
return;
}
//if ( pOther->pev->health <= 0 )
// return;
//pOther->TakeDamage ( pev, pev, gSkillData.plrDmgFlame, DMG_BURN );
//Boom();
SetThink ( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
#endif

//=========================================================
// Flamethrower
//=========================================================

LINK_ENTITY_TO_CLASS( weapon_flamethrower, CFlamethrower );

void CFlamethrower::Spawn( )
{
//pev->classname = MAKE_STRING("weapon_flamethrower"); // hack to allow for old names
Precache( );
m_iId = WEAPON_FLAMETHROWER;
SET_MODEL(ENT(pev), "models/w_flamethrower.mdl");

m_iDefaultAmmo = FLAMETHROWER_DEFAULT_GIVE;

FallInit();// get ready to fall down.
}

void CFlamethrower::Precache( void )
{
PRECACHE_MODEL("models/v_flamethrower.mdl");
PRECACHE_MODEL("models/w_flamethrower.mdl");
PRECACHE_MODEL("models/p_flamethrower.mdl");

PRECACHE_MODEL("sprites/flame_idle.spr");

PRECACHE_MODEL( FIRE_BEAM_SPRITE );

PRECACHE_SOUND("items/9mmclip1.wav");

UTIL_PrecacheOther( "ft_fireball" );

PRECACHE_SOUND ("weapons/357_cock1.wav");

m_usThrowerFire = PRECACHE_EVENT( 1, "events/thrower_start.sc" );
m_usThrowerStop = PRECACHE_EVENT( 1, "events/thrower_stop.sc" );
m_usThrowerFlame = PRECACHE_EVENT( 1, "events/thrower_flame.sc" );
}

int CFlamethrower::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "uranium";
p->iMaxAmmo1 = URANIUM_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 5;
p->iPosition = 1;
p->iId = m_iId = WEAPON_FLAMETHROWER;
p->iFlags = 0;
p->iWeight = FLAMETHROWER_WEIGHT;

return 1;
}

int CFlamethrower::AddToPlayer( CBasePlayer *pPlayer )
{
if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
{
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
WRITE_BYTE( m_iId );
MESSAGE_END();
return TRUE;
}
return FALSE;
}

BOOL CFlamethrower::Deploy( )
{
return DefaultDeploy( "models/v_flamethrower.mdl", "models/p_flamethrower.mdl", FLAME_DRAW, "shotgun" );
}

void CFlamethrower::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 16/30;
SendWeaponAnim( FLAME_HOLSTER );
}
void CFlamethrower::PrimaryAttack()
{
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound( );
m_flNextPrimaryAttack = 0.15;
return;
}

int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif

if ( m_iStartThrow == 1 )
{
if ( gpGlobals->time - m_flThrowTime >= 0.2 )
{
Throw();
}
else
{
//StartThrow();
Throw();
//m_iFlameRange = m_iFlameRange + 12;
}
}
else
{
//StartThrow();
Throw();
m_flThrowTime = gpGlobals->time;
m_iStartThrow = 1;
m_iThrowCount = 0;
//m_iFlameRange = m_iFlameRange + 12;
}

m_flTimeWeaponIdle = m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.03;
}

void CFlamethrower::StartThrow()
{
#ifndef CLIENT_DLL
ALERT ( at_console, "start throwing \n" );
#endif
}

void CFlamethrower::Throw()
{
float degree = 0.03;
Vector vecAiming = gpGlobals->v_forward;
Vector vecDir = gpGlobals->v_forward + Vector( RANDOM_FLOAT( -degree, degree ), RANDOM_FLOAT( -degree, degree ), RANDOM_FLOAT( -degree, degree ) );

if ( m_iStartThrow == 0 && m_iFlameRange != 38 )
m_iFlameRange = 38;

UTIL_MakeVectors( m_pPlayer->pev->v_angle );

//m_pPlayer-> // if player crouched??
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_right * 4 + gpGlobals->v_up * -8; // + gpGlobals->v_up * -9; //+ gpGlobals->v_forward * 32

TraceResult tr;
UTIL_TraceLine ( vecSrc, vecSrc + vecAiming * m_iFlameRange, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr );

#ifndef CLIENT_DLL
ALERT ( at_console, "throwing \n" );
CFireBall *pFireBall = CFireBall::CreateFireBall( tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer, this );//+ gpGlobals->v_right * RANDOM_FLOAT(-5,5) + gpGlobals->v_up * RANDOM_FLOAT(-5,5)

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 );
pFireBall->pev->velocity = ( vecDir * RANDOM_FLOAT( 600, 750) ) + ( gpGlobals->v_forward * DotProduct( m_pPlayer->pev->velocity, gpGlobals->v_forward ) ); //throw direction + random speed + speed of player
#endif
}

void CFlamethrower::StopThrow()
{
#ifndef CLIENT_DLL
ALERT ( at_console, "stop throwing \n" );
#endif

m_flThrowTime = 0;
m_iStartThrow = 0;
m_iThrowCount = 0;
}

void CFlamethrower::WeaponIdle( void )
{
ResetEmptySound( );

m_pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );

if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
return;

if ( m_iStartThrow == 1 )
{
StopThrow();
}

int iAnim;
switch ( RANDOM_LONG( 0, 1 ) )
{
case 0:
iAnim = FLAME_IDLE1;
break;

default:
case 1:
iAnim = FLAME_IDLE1;
break;
}

SendWeaponAnim( iAnim );
}

Post a Comment
click to sign in

You are not logged in, your comment will be anonymous unless you join the community today (totally free - or sign in with your social account on the right) which we encourage all contributors to do.

2000 characters limit; HTML formatting and smileys are not supported - text only

Level
93%
Gamer
7
Avatar
Avatar
Offline Since
Aug 15, 2014
Country
Germany Germany
Gender
Male
Member Watch
Track this member
Blog
Browse
Blogs
Views
43 (1 today)
Report Abuse
Report article