/*
===========================================================================
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
   )
   
   {

   }
