/*
Copyright (C) 1997-2001 Id Software, Inc.
Copyright (C) 2000-2002 Mr. Hyde and Mad Dog

This program 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.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "g_local.h"

void func_train_find (edict_t *self);
void SP_model_spawn (edict_t *ent);
void train_blocked (edict_t *self, edict_t *other);
void train_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
void train_use (edict_t *self, edict_t *other, edict_t *activator);

#define TRAIN_START_ON		     1
#define TRAIN_TOGGLE		     2
#define TRAIN_BLOCK_STOPS	     4
#define	PLAYER_MODEL             8
#define	NO_MODEL		        16
#define MTRAIN_ROTATE           32
#define MTRAIN_ROTATE_CONSTANT  64
#define TRAIN_SMOOTH           128

void model_train_animator(edict_t *animator)
{
	edict_t	*train;

	train = animator->owner;
	if(!train || !train->inuse)
	{
		G_FreeEdict(animator);
		return;
	}
	if(Q_stricmp(train->classname,"model_train"))
	{
		G_FreeEdict(animator);
		return;
	}
	animator->nextthink = level.time + FRAMETIME;
	if(VectorLength(train->velocity) == 0)
		return;
	train->s.frame++;
	if (train->s.frame >= train->framenumbers)
		train->s.frame = train->startframe;
	gi.linkentity(train);
}

void SP_model_train (edict_t *self)
{
	SP_model_spawn (self);

	self->class_id = ENTITY_MODEL_TRAIN;

	// Reset s.sound, which SP_model_spawn may have turned on
	self->moveinfo.sound_middle = self->s.sound;
	self->s.sound = 0;

	if(!self->inuse) return;

	// Reset some things from SP_model_spawn
	self->delay = 0;
	self->think = NULL;
	self->nextthink = 0;
	if (self->health)
	{
		self->die = train_die;
		self->takedamage = DAMAGE_YES;
	}

	if(self->framenumbers > self->startframe+1)
	{
		edict_t	*animator;
		animator = G_Spawn();
		animator->owner = self;
		animator->think = model_train_animator;
		animator->nextthink = level.time + FRAMETIME;
	}
	self->s.frame = self->startframe;
	self->movetype = MOVETYPE_PUSH;

	// Really gross stuff here... translate model_spawn spawnflags
	// to func_train spawnflags. PLAYER_MODEL and NO_MODEL have
	// already been checked in SP_model_spawn and are never re-used,
	// so it's OK to overwrite those.
	if(self->spawnflags & MTRAIN_ROTATE)
	{
		self->spawnflags &= ~MTRAIN_ROTATE;
		self->spawnflags |= TRAIN_ROTATE;
	}
	if(self->spawnflags & MTRAIN_ROTATE_CONSTANT)
	{
		self->spawnflags &= ~MTRAIN_ROTATE_CONSTANT;
		self->spawnflags |= TRAIN_ROTATE_CONSTANT;
	}
	if( (self->spawnflags & (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT)) == (TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT))
	{
		self->spawnflags &= ~(TRAIN_ROTATE | TRAIN_ROTATE_CONSTANT);
		self->spawnflags |= TRAIN_SPLINE;
	}
	if(self->style == 3)
		self->spawnflags |= TRAIN_ANIMATE;		// 32
	if(self->style == 4)
		self->spawnflags |= TRAIN_ANIMATE_FAST;	// 64

	// TRAIN_SMOOTH forces trains to go directly to Move_Done from
	// Move_Final rather than slowing down (if necessary) for one
	// frame.
	if (self->spawnflags & TRAIN_SMOOTH)
		self->smooth_movement = true;
	else
		self->smooth_movement = false;

	self->blocked = train_blocked;
	if (self->spawnflags & TRAIN_BLOCK_STOPS)
		self->dmg = 0;
	else
	{
		if (!self->dmg)
			self->dmg = 100;
	}

	if (!self->speed)
		self->speed = 100;

	self->moveinfo.speed = self->speed;
	self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed;

	self->use = train_use;

	gi.linkentity (self);

	if (self->target)
	{
		// start trains on the second frame, to make sure their targets have had
		// a chance to spawn
		self->nextthink = level.time + FRAMETIME;
		self->think = func_train_find;
	}
	else
	{
		gi.dprintf ("model_train without a target at %s\n", vtos(self->absmin));
	}

}

void SP_model_train_origin (edict_t *self)
{
	self->spawnflags |= TRAIN_ORIGIN;
	SP_model_train (self);
}
