266 lines
5.1 KiB
C++
266 lines
5.1 KiB
C++
// Copyright (C) 1998 by Ritual Entertainment, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source is may not be distributed and/or modified without
|
|
// expressly written permission by Ritual Entertainment, Inc.
|
|
//
|
|
// DESCRIPTION:
|
|
// Peon
|
|
//
|
|
|
|
#include "g_local.h"
|
|
#include "actor.h"
|
|
#include "specialfx.h"
|
|
#include "surface.h"
|
|
#include "peon.h"
|
|
|
|
|
|
class EXPORT_FROM_DLL Goo : public Projectile
|
|
{
|
|
public:
|
|
CLASS_PROTOTYPE( Goo );
|
|
|
|
Goo();
|
|
virtual void Setup( Entity *owner, Vector pos, Vector vel );
|
|
virtual void GooTouch( Event *ev );
|
|
};
|
|
|
|
CLASS_DECLARATION( Projectile, Goo, NULL );
|
|
|
|
ResponseDef Goo::Responses[] =
|
|
{
|
|
{ &EV_Touch, ( Response )Goo::GooTouch },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
Goo::Goo()
|
|
{
|
|
}
|
|
|
|
void Goo::GooTouch
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
Entity *other;
|
|
Entity *owner;
|
|
int damg;
|
|
Vector v;
|
|
Vector norm;
|
|
Vector shockangles;
|
|
|
|
other = ev->GetEntity( 1 );
|
|
assert( other );
|
|
|
|
if ( other->isSubclassOf( Teleporter ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( other->entnum == this->owner )
|
|
{
|
|
return;
|
|
}
|
|
|
|
owner = G_GetEntity( this->owner );
|
|
|
|
if ( !owner )
|
|
owner = world;
|
|
|
|
setSolidType( SOLID_NOT );
|
|
|
|
// Hit the shy, so remove everything
|
|
if ( HitSky() )
|
|
{
|
|
PostEvent( EV_Remove, 0 );
|
|
return;
|
|
}
|
|
|
|
damg = 40 + ( int )G_Random( 40 );
|
|
|
|
// Single player packs a bigger punch
|
|
if ( !deathmatch->value && owner->isClient() )
|
|
damg *= 1.5;
|
|
|
|
if ( other->takedamage )
|
|
other->Damage( this, owner, damg, worldorigin, velocity, level.impact_trace.plane.normal, 32, 0, MOD_PULSE, -1, -1, 1.0f );
|
|
|
|
if ( other == world )
|
|
{
|
|
RandomAnimate( "splat", NULL );
|
|
PostEvent( EV_Remove, 5 );
|
|
}
|
|
else
|
|
{
|
|
PostEvent( EV_Remove, 0 );
|
|
}
|
|
}
|
|
|
|
void Goo::Setup
|
|
(
|
|
Entity *owner,
|
|
Vector pos,
|
|
Vector vel
|
|
)
|
|
|
|
{
|
|
this->owner = owner->entnum;
|
|
edict->owner = owner->edict;
|
|
|
|
// Align the projectile
|
|
angles = vel.toAngles();
|
|
angles[ PITCH ] = -angles[ PITCH ];
|
|
setAngles( angles );
|
|
// edict->s.angles[ROLL] = rand() % 360;
|
|
|
|
// Flies like a grenade
|
|
setMoveType( MOVETYPE_TOSS );
|
|
setSolidType( SOLID_BBOX );
|
|
edict->clipmask = MASK_PROJECTILE;
|
|
setModel( "goo.def" );
|
|
RandomAnimate( "goo", NULL );
|
|
|
|
// Set the flying velocity
|
|
velocity = vel;
|
|
|
|
takedamage = DAMAGE_NO;
|
|
|
|
if ( G_Random( 10 ) < 2 )
|
|
{
|
|
// Set the light and effects
|
|
edict->s.renderfx |= RF_DLIGHT;
|
|
edict->s.radius = 100;
|
|
edict->s.color_r = 0.1f;
|
|
edict->s.color_g = 0.9f;
|
|
edict->s.color_b = 0.1f;
|
|
}
|
|
|
|
flags |= FL_DONTSAVE;
|
|
|
|
edict->s.effects |= EF_WARM; //### give off a heat signature
|
|
|
|
// Set size and origin
|
|
setSize( "-1 -1 -1", "1 1 1" );
|
|
setOrigin( pos );
|
|
worldorigin.copyTo(edict->s.old_origin);
|
|
|
|
// Remove the projectile in the future
|
|
PostEvent( EV_Remove, 30 );
|
|
}
|
|
|
|
CLASS_DECLARATION( Actor, Peon, "monster_peon" );
|
|
|
|
Event EV_Peon_SpawnGoo( "spawngoo" );
|
|
|
|
ResponseDef Peon::Responses[] =
|
|
{
|
|
{ &EV_Peon_SpawnGoo, ( Response )Peon::SpawnGoo },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
Peon::Peon()
|
|
{
|
|
gootime = 0;
|
|
setModel( "peon.def" );
|
|
modelIndex( "goo.def" );
|
|
}
|
|
|
|
void Peon::SpawnGoo
|
|
(
|
|
Event *ev
|
|
)
|
|
|
|
{
|
|
Goo * goo;
|
|
Vector vel;
|
|
Vector pos;
|
|
Vector target;
|
|
float speed;
|
|
char bonename[ 32 ];
|
|
int num;
|
|
|
|
if ( !currentEnemy )
|
|
return;
|
|
|
|
num = (int)G_Random( 6 ) + 1;
|
|
sprintf( bonename, "goo%d", num );
|
|
|
|
GetBone( bonename, &pos, NULL, NULL, NULL );
|
|
|
|
pos += worldorigin;
|
|
|
|
speed = 900;
|
|
|
|
target = G_PredictPosition( pos, currentEnemy->centroid, currentEnemy->velocity, speed );
|
|
|
|
vel = G_CalculateImpulse
|
|
(
|
|
pos,
|
|
target,
|
|
speed,
|
|
1
|
|
);
|
|
goo = new Goo;
|
|
goo->Setup( this, pos, vel );
|
|
}
|
|
|
|
void Peon::Prethink
|
|
(
|
|
void
|
|
)
|
|
{
|
|
if ( currentEnemy && ( gootime < level.time ) )
|
|
{
|
|
Vector delta;
|
|
Vector dir;
|
|
ScriptVariable * stage;
|
|
int stagenum;
|
|
|
|
stage = levelVars.GetVariable( "eonpeon_stage" );
|
|
if ( stage )
|
|
{
|
|
stagenum = stage->intValue();
|
|
}
|
|
else
|
|
{
|
|
stagenum = 0;
|
|
}
|
|
if ( stagenum < 2 )
|
|
{
|
|
gootime = level.time + 1;
|
|
}
|
|
else
|
|
{
|
|
dir = Vector( orientation[ 0 ] );
|
|
delta = currentEnemy->centroid - centroid;
|
|
if ( delta.length() < 1000 )
|
|
{
|
|
#if 0
|
|
float dot;
|
|
|
|
dot = delta * dir;
|
|
|
|
if ( dot < -0.5f )
|
|
{
|
|
gootime = level.time + 5;
|
|
DoAction( "rearattack", false );
|
|
}
|
|
#else
|
|
if ( stagenum == 2 )
|
|
gootime = level.time + 5;
|
|
else
|
|
gootime = level.time;
|
|
|
|
DoAction( "rearattack", false );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// call our superclass
|
|
//
|
|
Actor::Prethink();
|
|
}
|
|
|