sin-sdk/gibs.cpp

302 lines
6.7 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/gibs.cpp $
// $Revision:: 21 $
// $Author:: Jimdose $
// $Date:: 11/19/98 9:29p $
//
// 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.
//
// $Log:: /Quake 2 Engine/Sin/code/game/gibs.cpp $
//
// 21 11/19/98 9:29p Jimdose
// gibs copy gravaxis
//
// 20 11/09/98 1:09a Aldie
// Changed fadesplat to fade in 30 secs
//
// 19 11/08/98 8:31p Aldie
// Added ability to not fade splats
//
// 18 10/22/98 9:30p Aldie
// Modified gib physics a little
//
// 17 10/07/98 11:51p Jimdose
// moved body_parts out of game structure
//
// 16 9/22/98 5:26p Markd
// fixed small gib bug
//
// 15 9/22/98 5:19p Markd
// Put in new consolidated gib function
//
// 14 9/20/98 5:11p Aldie
// Added blood trail to gib constructor
//
// 13 8/29/98 9:43p Jimdose
// Added call info to G_Trace
//
// 12 8/27/98 9:02p Jimdose
// Changed centroid to a variable
//
// 11 8/19/98 8:49p Aldie
// Increased gibbage velocity
//
// 10 8/10/98 6:52p Aldie
// Changed the gib throwing code
//
// 9 7/29/98 2:31p Aldie
// Changed health to a float
//
// 8 7/26/98 3:58p Aldie
// Reversed a logic bug
//
// 7 7/25/98 8:39p Aldie
// Bloodsplat only in single player
//
// 6 7/24/98 10:04p Aldie
// Changed the gibs layout
//
// 5 7/23/98 6:55p Aldie
// Fun with gibs
//
// 4 7/23/98 6:17p Aldie
// Updated damage system and fixed some damage related bugs. Also put tracers
// back to the way they were, and added gib event to funcscriptmodels
//
// 3 6/30/98 12:40p Aldie
// Changed bloodsplat scale.
//
// 2 5/27/98 5:03a Aldie
// First version of gibs
//
// DESCRIPTION:
// Gibs - nuff said
#include "gibs.h"
const char *body_parts[] =
{
"gib1.def", "gibtorso.def", "gibhead.def", "gibleg.def"
//"gib1.def", "gib2.def", "gibhead.def", "gibleg.def", "gibarm.def", "gibribs.def"
};
const int num_body_parts = ( sizeof( body_parts ) / sizeof( body_parts[ 0 ] ) );
CLASS_DECLARATION( Entity, Gib, "gib" );
Event EV_ThrowGib("throwgib");
ResponseDef Gib::Responses[] =
{
{ &EV_ThrowGib, ( Response )Gib::Throw },
{ &EV_Touch, ( Response )Gib::Splat },
{ NULL, NULL }
};
Gib::Gib
(
const char *name,
qboolean blood_trail
)
{
setSize("0 0 0", "0 0 0");
setModel(name);
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
if ( blood_trail )
edict->s.effects |= EF_GIB;
sprayed = false;
fadesplat = true;
}
Gib::Gib()
{
setSize("0 0 0", "0 0 0");
setModel("gib1.def");
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
edict->s.effects |= EF_GIB;
sprayed = false;
fadesplat = true;
}
void Gib::Splat
(
Event *ev
)
{
Vector end;
if (deathmatch->value)
return;
if (!sv_gore->value)
return;
if (sprayed)
return;
sprayed = true;
end = origin;
end.z -= 1024;
SprayBlood(origin, end, 25);
setSolidType(SOLID_NOT);
}
void Gib::SprayBlood
(
Vector start,
Vector end,
int damage
)
{
trace_t trace;
float dist;
float scale;
Entity *splat;
Vector norm;
trace = G_Trace( start, vec_zero, vec_zero, end, NULL, MASK_SOLIDNONFENCE, "Gib::SprayBlood" );
if ( HitSky( &trace ) || ( trace.ent->solid != SOLID_BSP ) )
{
return;
}
dist = ( Vector( trace.endpos ) - start ).length();
scale = ( float )damage / ( dist * 0.3 );
if ( scale > 0.6 )
{
scale = 0.6;
}
if ( scale < 0.02 )
{
return;
}
// Do a bloodsplat
splat = new Entity;
splat->setMoveType( MOVETYPE_NONE );
splat->setSolidType( SOLID_NOT );
splat->setModel( "sprites/bloodsplat.spr" );
splat->edict->s.frame = G_Random( 4 );
splat->setSize( "0 0 0", "0 0 0" );
splat->edict->s.scale = scale * this->edict->s.scale;
norm = trace.plane.normal;
norm.x = -norm.x;
norm.y = -norm.y;
splat->angles = norm.toAngles();
splat->angles.z = G_Random( 360 );
splat->setAngles( splat->angles );
splat->setOrigin( Vector( trace.endpos ) + ( Vector( trace.plane.normal ) * 0.2 ) );
if ( fadesplat )
splat->PostEvent( EV_FadeOut, 3 );
else
splat->PostEvent( EV_FadeOut, 30 );
}
void Gib::ClipGibVelocity
(
void
)
{
if (velocity[0] < -400)
velocity[0] = -400;
else if (velocity[0] > 400)
velocity[0] = 400;
if (velocity[1] < -400)
velocity[1] = -400;
else if (velocity[1] > 400)
velocity[1] = 400;
if (velocity[2] < 200)
velocity[2] = 200; // always some upwards
else if (velocity[2] > 600)
velocity[2] = 600;
}
void Gib::SetVelocity
(
float damage
)
{
velocity[0] = 100.0 * crandom();
velocity[1] = 100.0 * crandom();
velocity[2] = 200.0 + 100.0 * random();
avelocity = Vector( G_Random( 600 ), G_Random( 600 ), G_Random( 600 ) );
if ( ( damage < -150 ) && ( G_Random() > 0.95f ) )
velocity *= 2.0f;
else if ( damage < -100 )
velocity *= 1.5f;
ClipGibVelocity();
}
void Gib::Throw
(
Event *ev
)
{
Entity *ent;
ent = ev->GetEntity(1);
setOrigin(ent->centroid);
worldorigin.copyTo(edict->s.old_origin);
SetVelocity(ev->GetInteger(2));
edict->s.scale = ev->GetFloat(3);
PostEvent(EV_FadeOut, 10 + G_Random(5));
}
void CreateGibs
(
Entity * ent,
float damage,
float scale,
int num,
const char * modelname
)
{
int i;
Gib * gib;
assert( ent );
if ( !ent )
return;
ent->RandomGlobalSound( "impact_gib" );
for ( i = 0; i < num; i++ )
{
if ( modelname )
{
gib = new Gib( modelname );
}
else
{
gib = new Gib( body_parts[ i % num_body_parts ] );
}
gib->setOrigin(ent->centroid);
gib->worldorigin.copyTo(gib->edict->s.old_origin);
gib->SetVelocity( damage );
gib->edict->s.scale = scale + G_Random( scale * 0.3 );
gib->SetGravityAxis( ent->gravaxis );
gib->PostEvent(EV_FadeOut, 10 + G_Random(5));
}
}