/* =========================================================================== Copyright (C) 2015 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // gibs.cpp: Gibs - nuff said #include "gibs.h" #include "decals.h" #include "level.h" #include "g_phys.h" Event EV_ThrowGib ( "throwgib", EV_DEFAULT, "eif", "ent velocity scale", "Throw a gib.", EV_NORMAL ); CLASS_DECLARATION( Mover, Gib, "gib" ) { { &EV_ThrowGib, &Gib::Throw }, { &EV_Touch, &Gib::Splat }, { &EV_Stop, &Gib::Stop }, { &EV_Damage, &Gib::Damage }, { NULL, NULL } }; Gib::Gib ( str name, qboolean blood_trail, str bloodtrailname, str bloodspurtname, str bloodsplatname, float bloodsplatsize, float pitch ) { setSize( Vector( "0 0 0" ), Vector( "0 0 0" ) ); if ( name.length() ) setModel( name.c_str() ); setMoveType( MOVETYPE_GIB ); setSolidType( SOLID_BBOX ); takedamage = DAMAGE_YES; sprayed = false; fadesplat = true; scale = 2.0f; next_bleed_time = 0; final_pitch = pitch; if ( blood_trail ) { // Make a blood emitter and bind it to the head blood = new Mover; if ( bloodtrailname.length() ) blood->setModel( bloodtrailname.c_str() ); blood->setMoveType( MOVETYPE_BOUNCE ); blood->setSolidType( SOLID_NOT ); blood->bind( this ); // Save the blood spurt name if ( bloodspurtname.length() ) blood_spurt_name = bloodspurtname; // Save the blood splat name if ( bloodsplatname.length() ) blood_splat_name = bloodsplatname; blood_splat_size = bloodsplatsize; } else { blood = NULL; } Sound( "snd_decap", CHAN_BODY, 1, 300 ); } Gib::~Gib() { if ( blood ) blood->PostEvent( EV_Remove, 0 ); blood = NULL; } Gib::Gib() { if ( LoadingSavegame ) { return; } setSize( Vector( "0 0 0" ), Vector( "0 0 0" ) ); setModel("gib1.def"); setMoveType( MOVETYPE_GIB ); setSolidType( SOLID_BBOX ); sprayed = 0; fadesplat = true; scale = 2.0f; } void Gib::Stop ( Event *ev ) { //setSolidType( SOLID_NOT ); if ( blood ) blood->PostEvent( EV_Remove, 0 ); blood = NULL; } void Gib::Splat ( Event *ev ) { if ( g_gametype->integer != GT_SINGLE_PLAYER ) return; if ( sprayed > 3 ) { //setSolidType(SOLID_NOT); return; } sprayed++; scale -= 0.2f; // Stop spinning / force to final pitch avelocity = vec_zero; if ( final_pitch != NO_FINAL_PITCH ) { angles[PITCH] = final_pitch; setAngles( angles ); } SprayBlood( origin ); Sound( "snd_gibhit" ); } void Gib::Damage ( Event *ev ) { Vector direction; Entity *blood; Vector dir; if ( next_bleed_time > level.time ) return; direction = ev->GetVector ( 5 ); // Spawn a blood spurt if ( blood_spurt_name.length() > 0 ) { blood = new Animate; blood->setModel( blood_spurt_name.c_str() ); dir[0] = -direction[0]; dir[1] = -direction[1]; dir[2] = -direction[2]; blood->angles = dir.toAngles(); blood->setAngles( blood->angles ); blood->setOrigin( centroid ); blood->origin.copyTo( blood->edict->s.origin2 ); blood->setSolidType( SOLID_NOT ); blood->PostEvent( EV_Remove, 1 ); next_bleed_time = level.time + 0.5; } } void Gib::SprayBlood ( Vector start ) { Vector norm; trace_t trace; Vector trace_end; trace_end = velocity; trace_end.normalize(); trace_end *= 1000; trace_end += start; trace = G_Trace( start, vec_zero, vec_zero, trace_end, this, MASK_SOLID, false, "Gib::SprayBlood" ); if ( HitSky( &level.impact_trace ) || ( !level.impact_trace.ent ) || ( level.impact_trace.ent->solid != SOLID_BSP ) ) { return; } // Do a bloodsplat if ( blood_splat_name.length() ) { Decal *decal = new Decal; decal->setShader( blood_splat_name ); decal->setOrigin( Vector( trace.endpos ) + ( Vector( level.impact_trace.plane.normal ) * 0.2f ) ); decal->setDirection( level.impact_trace.plane.normal ); decal->setOrientation( "random" ); decal->setRadius( blood_splat_size + G_Random( blood_splat_size ) ); } } 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); origin.copyTo(edict->s.origin2); 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 ) { }