ef2gamesource/dlls/game/goo.cpp

236 lines
5.1 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /EF2/Code/DLLs/game/goo.cpp $
// $Revision:: 7 $
// $Author:: Singlis $
// $Date:: 9/26/03 2:36p $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
//
// DESCRIPTION:
// Goo Gun Projectile
#include "_pch_cpp.h"
#include "goo.h"
Event EV_GooDebris_Prethink
(
"_prethink",
EV_CODEONLY,
NULL,
NULL,
"Think function for the debris"
);
CLASS_DECLARATION( Projectile, GooDebris, NULL )
{
{ &EV_GooDebris_Prethink, &GooDebris::Prethink },
{ &EV_Touch, &GooDebris::Touch },
{ NULL, NULL }
};
GooDebris::GooDebris()
{
nexttouch = 0;
}
void GooDebris::Prethink( Event *ev )
{
if ( ( velocity.length() < 30.0f ) && ( CurrentAnim() == gi.Anim_NumForName( edict->s.modelindex, "idle" ) ) )
{
velocity = Vector( 0.0f, 0.0f, 0.0f );
animate->RandomAnimate( "splat" );
}
if ( ( level.time - this->edict->spawntime ) > 5.0f )
{
edict->s.scale *= 0.95f;
}
if ( edict->s.scale < 0.1f )
{
PostEvent( EV_Remove, 0.0f );
}
else
{
Event *ev1 = new Event( ev );
PostEvent( ev1, level.frametime );
}
}
void GooDebris::Touch( Event *ev )
{
Entity *other;
Entity *owner;
Vector ang;
other = ev->GetEntity( 1 );
if ( other == world )
{
vectoangles( level.impact_trace.plane.normal, ang );
setAngles( ang );
}
if ( level.time < nexttouch )
{
return;
}
nexttouch = level.time + 0.5f;
if ( !other || !other->isSubclassOf( Sentient ) )
{
return;
}
owner = G_GetEntity( this->owner );
if ( !owner )
{
owner = world;
}
if ( !other )
{
return;
}
other->Damage( this, owner, damage, origin, Vector( 0.0f, 0.0f, 0.0f ), Vector( 0.0f, 0.0f, 0.0f ), 0, 0, meansofdeath );
}
Event EV_Goo_DebrisModel
(
"goodebrismodel",
EV_TIKIONLY,
"s",
"modelname",
"Model name for the debris that is spawned on explosion"
);
Event EV_Goo_DebrisCount
(
"goodebriscount",
EV_TIKIONLY,
"i",
"count",
"Number of pieces of debris to spawn"
);
CLASS_DECLARATION( Projectile, GooProjectile, NULL )
{
{ &EV_Goo_DebrisModel, &GooProjectile::SetDebrisModel },
{ &EV_Goo_DebrisCount, &GooProjectile::SetDebrisCount },
{ NULL, NULL }
};
GooProjectile::GooProjectile()
{
m_debrismodel = "fx_goo_debris.tik";
m_debriscount = 3;
}
void GooProjectile::SetDebrisModel( Event *ev )
{
m_debrismodel = ev->GetString( 1 );
}
void GooProjectile::SetDebrisCount( Event *ev )
{
m_debriscount = ev->GetInteger( 1 );
}
void GooProjectile::Explode( Event *ev )
{
int i;
Entity *owner;
Entity *ignoreEnt=NULL;
if ( ev->NumArgs() == 1 )
ignoreEnt = ev->GetEntity( 1 );
// Get the owner of this projectile
owner = G_GetEntity( this->owner );
// If the owner's not here, make the world the owner
if ( !owner )
owner = world;
takedamage = DAMAGE_NO;
// Spawn an explosion model
if ( explosionmodel.length() )
{
// Move the projectile back off the surface a bit so we can see
// explosion effects.
Vector dir, v;
v = velocity;
v.normalize();
dir = v;
v = origin - v * 36.0f;
setOrigin( v );
ExplosionAttack( v, owner, explosionmodel, dir, ignoreEnt );
}
CancelEventsOfType( EV_Projectile_UpdateBeam );
// Kill the beam
if ( m_beam )
{
m_beam->ProcessEvent( EV_Remove );
m_beam = NULL;
}
// When the goo hits something, spawn debris
for ( i=0; i<m_debriscount; i++ )
{
GooDebris *proj;
Vector dir;
dir = Vector( level.impact_trace.plane.normal );
dir += Vector( crandom() * 0.5, crandom() * 0.5f, 0.0f );
proj = ( GooDebris * )ProjectileAttack( this->origin, dir, this, m_debrismodel, 1.0f );
if ( !proj )
{
warning( "GooProjectile::Explode", "Could not create debris projectile" );
return;
}
proj->owner = ENTITYNUM_WORLD;
proj->setSolidType( SOLID_TRIGGER );
proj->avelocity = Vector( G_CRandom( 360.0f ), G_CRandom( 360.0f ), G_CRandom( 360.0f ) );
proj->setSize( Vector( -16.0f, -16.0f, 0.0f ) * proj->edict->s.scale, Vector( 16.0f ,16.0f ,32.0f ) * proj->edict->s.scale );
proj->setMoveType( MOVETYPE_TOSS );
proj->PostEvent( EV_GooDebris_Prethink, level.frametime );
}
// Change to the splat
if ( level.impact_trace.ent && ( level.impact_trace.ent->solid == SOLID_BSP ) )
{
GooDebris *p;
Vector ang;
p = new GooDebris;
vectoangles( level.impact_trace.plane.normal, ang );
p->setAngles( ang );
p->setModel( this->model );
p->ProcessInitCommands( p->edict->s.modelindex );
p->setSize( Vector( -16.0f, -16.0f, 0.0f ) * p->edict->s.scale, Vector( 16.0f, 16.0f, 32.0f ) * p->edict->s.scale );
p->setOrigin( this->origin );
p->velocity = Vector( 0.0f, 0.0f, 0.0f );
p->setMoveType( MOVETYPE_FLY );
p->setSolidType( SOLID_TRIGGER );
p->animate->RandomAnimate( "splat" );
p->owner = this->owner;
p->PostEvent( EV_GooDebris_Prethink, level.frametime ); // shrink out
}
}