/*
==============================================================================

insane

==============================================================================
*/

#include "../../header/local.h"
#include "insane.h"


static int	sound_fist;
static int	sound_shake;
static int	sound_moan;
static int	sound_scream[8];

void insane_fist (edict_t *self)
{
	gi.sound (self, CHAN_VOICE, sound_fist, 1, ATTN_IDLE, 0);
}

void insane_shake (edict_t *self)
{
	gi.sound (self, CHAN_VOICE, sound_shake, 1, ATTN_IDLE, 0);
}

void insane_moan (edict_t *self)
{
	gi.sound (self, CHAN_VOICE, sound_moan, 1, ATTN_IDLE, 0);
}

void insane_scream (edict_t *self)
{
	gi.sound (self, CHAN_VOICE, sound_scream[rand()%8], 1, ATTN_IDLE, 0);
}


void insane_stand (edict_t *self);
void insane_dead (edict_t *self);
void insane_cross (edict_t *self);
void insane_walk (edict_t *self);
void insane_run (edict_t *self);
void insane_checkdown (edict_t *self);
void insane_checkup (edict_t *self);
void insane_onground (edict_t *self);


mframe_t insane_frames_stand_normal [] =
{
	{ai_stand, 0, NULL},
	{ai_stand, 0, NULL},
	{ai_stand, 0, NULL},
	{ai_stand, 0, NULL},
	{ai_stand, 0, NULL},
	{ai_stand, 0, insane_checkdown}
};
mmove_t insane_move_stand_normal = {FRAME_stand60, FRAME_stand65, insane_frames_stand_normal, insane_stand};

mframe_t insane_frames_stand_insane [] =
{
	{ai_stand,	0,	insane_shake},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	NULL},
	{ai_stand,	0,	insane_checkdown}
};
mmove_t insane_move_stand_insane = {FRAME_stand65, FRAME_stand94, insane_frames_stand_insane, insane_stand};

mframe_t insane_frames_uptodown [] =
{
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	insane_moan},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},

	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},

	{ai_move,	2.7,	NULL},
	{ai_move,	4.1,	NULL},
	{ai_move,	6,		NULL},
	{ai_move,	7.6,	NULL},
	{ai_move,	3.6,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	insane_fist},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},

	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	insane_fist},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL},
	{ai_move,	0,	NULL}
};
mmove_t insane_move_uptodown = {FRAME_stand1, FRAME_stand40, insane_frames_uptodown, insane_onground};


mframe_t insane_frames_downtoup [] =
{
	{ai_move,	-0.7,	NULL},			// 41
	{ai_move,	-1.2,	NULL},			// 42
	{ai_move,	-1.5,		NULL},		// 43
	{ai_move,	-4.5,		NULL},		// 44
	{ai_move,	-3.5,	NULL},			// 45
	{ai_move,	-0.2,	NULL},			// 46
	{ai_move,	0,	NULL},			// 47
	{ai_move,	-1.3,	NULL},			// 48
	{ai_move,	-3,	NULL},				// 49
	{ai_move,	-2,	NULL},			// 50
	{ai_move,	0,	NULL},				// 51
	{ai_move,	0,	NULL},				// 52
	{ai_move,	0,	NULL},				// 53
	{ai_move,	-3.3,	NULL},			// 54
	{ai_move,	-1.6,	NULL},			// 55
	{ai_move,	-0.3,	NULL},			// 56
	{ai_move,	0,	NULL},				// 57
	{ai_move,	0,	NULL},				// 58
	{ai_move,	0,	NULL}				// 59
};
mmove_t insane_move_downtoup = {FRAME_stand41, FRAME_stand59, insane_frames_downtoup, insane_stand};

mframe_t insane_frames_jumpdown [] =
{
	{ai_move,	0.2,	NULL},
	{ai_move,	11.5,	NULL},
	{ai_move,	5.1,	NULL},
	{ai_move,	7.1,	NULL},
	{ai_move,	0,	NULL}
};
mmove_t insane_move_jumpdown = {FRAME_stand96, FRAME_stand100, insane_frames_jumpdown, insane_onground};


mframe_t insane_frames_down [] =
{
	{ai_move,	0,		NULL},		// 100
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},		// 110
	{ai_move,	-1.7,		NULL},
	{ai_move,	-1.6,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		insane_fist},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},		// 120
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},		// 130
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		insane_moan},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},		// 140
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},		// 150
	{ai_move,	0.5,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	-0.2,		insane_scream},
	{ai_move,	0,		NULL},
	{ai_move,	0.2,		NULL},
	{ai_move,	0.4,		NULL},
	{ai_move,	0.6,		NULL},
	{ai_move,	0.8,		NULL},
	{ai_move,	0.7,		NULL},
	{ai_move,	0,		insane_checkup}		// 160
};
mmove_t insane_move_down = {FRAME_stand100, FRAME_stand160, insane_frames_down, insane_onground};

mframe_t insane_frames_walk_normal [] =
{
	{ai_walk,	0,		insane_scream},
	{ai_walk,	2.5,	NULL},
	{ai_walk,	3.5,	NULL},
	{ai_walk,	1.7,	NULL},
	{ai_walk,	2.3,	NULL},
	{ai_walk,	2.4,	NULL},
	{ai_walk,	2.2,	NULL},
	{ai_walk,	4.2,	NULL},
	{ai_walk,	5.6,	NULL},
	{ai_walk,	3.3,	NULL},
	{ai_walk,	2.4,	NULL},
	{ai_walk,	0.9,	NULL},
	{ai_walk,	0,		NULL}
};
mmove_t insane_move_walk_normal = {FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_walk};
mmove_t insane_move_run_normal = {FRAME_walk27, FRAME_walk39, insane_frames_walk_normal, insane_run};

mframe_t insane_frames_walk_insane [] =
{
	{ai_walk,	0,		insane_scream},		// walk 1
	{ai_walk,	3.4,	NULL},		// walk 2
	{ai_walk,	3.6,	NULL},		// 3
	{ai_walk,	2.9,	NULL},		// 4
	{ai_walk,	2.2,	NULL},		// 5
	{ai_walk,	2.6,	NULL},		// 6
	{ai_walk,	0,		NULL},		// 7
	{ai_walk,	0.7,	NULL},		// 8
	{ai_walk,	4.8,	NULL},		// 9
	{ai_walk,	5.3,	NULL},		// 10
	{ai_walk,	1.1,	NULL},		// 11
	{ai_walk,	2,		NULL},		// 12
	{ai_walk,	0.5,	NULL},		// 13
	{ai_walk,	0,		NULL},		// 14
	{ai_walk,	0,		NULL},		// 15
	{ai_walk,	4.9,	NULL},		// 16
	{ai_walk,	6.7,	NULL},		// 17
	{ai_walk,	3.8,	NULL},		// 18
	{ai_walk,	2,		NULL},		// 19
	{ai_walk,	0.2,	NULL},		// 20
	{ai_walk,	0,		NULL},		// 21
	{ai_walk,	3.4,	NULL},		// 22
	{ai_walk,	6.4,	NULL},		// 23
	{ai_walk,	5,		NULL},		// 24
	{ai_walk,	1.8,	NULL},		// 25
	{ai_walk,	0,		NULL}		// 26
};
mmove_t insane_move_walk_insane = {FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_walk};
mmove_t insane_move_run_insane = {FRAME_walk1, FRAME_walk26, insane_frames_walk_insane, insane_run};

mframe_t insane_frames_stand_pain [] =
{
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL}
};
mmove_t insane_move_stand_pain = {FRAME_st_pain2, FRAME_st_pain12, insane_frames_stand_pain, insane_run};

mframe_t insane_frames_stand_death [] =
{
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL}
};
mmove_t insane_move_stand_death = {FRAME_st_death2, FRAME_st_death18, insane_frames_stand_death, insane_dead};

mframe_t insane_frames_crawl [] =
{
	{ai_walk,	0,		insane_scream},
	{ai_walk,	1.5,	NULL},
	{ai_walk,	2.1,	NULL},
	{ai_walk,	3.6,	NULL},
	{ai_walk,	2,		NULL},
	{ai_walk,	0.9,	NULL},
	{ai_walk,	3,		NULL},
	{ai_walk,	3.4,	NULL},
	{ai_walk,	2.4,	NULL}
};
mmove_t insane_move_crawl = {FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL};
mmove_t insane_move_runcrawl = {FRAME_crawl1, FRAME_crawl9, insane_frames_crawl, NULL};

mframe_t insane_frames_crawl_pain [] =
{
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL}
};
mmove_t insane_move_crawl_pain = {FRAME_cr_pain2, FRAME_cr_pain10, insane_frames_crawl_pain, insane_run};

mframe_t insane_frames_crawl_death [] =
{
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL}
};
mmove_t insane_move_crawl_death = {FRAME_cr_death10, FRAME_cr_death16, insane_frames_crawl_death, insane_dead};

mframe_t insane_frames_cross [] =
{
	{ai_move,	0,		insane_moan},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL}
};
mmove_t insane_move_cross = {FRAME_cross1, FRAME_cross15, insane_frames_cross, insane_cross};

mframe_t insane_frames_struggle_cross [] =
{
	{ai_move,	0,		insane_scream},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL},
	{ai_move,	0,		NULL}
};
mmove_t insane_move_struggle_cross = {FRAME_cross16, FRAME_cross30, insane_frames_struggle_cross, insane_cross};

void insane_cross (edict_t *self)
{
	if (random() < 0.8)		
		self->monsterinfo.currentmove = &insane_move_cross;
	else
		self->monsterinfo.currentmove = &insane_move_struggle_cross;
}

void insane_walk (edict_t *self)
{
	if ( self->spawnflags & 16 )			// Hold Ground?
		if (self->s.frame == FRAME_cr_pain10)
		{
			self->monsterinfo.currentmove = &insane_move_down;
			return;
		}
	if (self->spawnflags & 4)
		self->monsterinfo.currentmove = &insane_move_crawl;
	else
		if (random() <= 0.5)
			self->monsterinfo.currentmove = &insane_move_walk_normal;
		else
			self->monsterinfo.currentmove = &insane_move_walk_insane;
}

void insane_run (edict_t *self)
{
	if ( self->spawnflags & 16 )			// Hold Ground?
		if (self->s.frame == FRAME_cr_pain10)
		{
			self->monsterinfo.currentmove = &insane_move_down;
			return;
		}
	if (self->spawnflags & 4)				// Crawling?
		self->monsterinfo.currentmove = &insane_move_runcrawl;
	else
		if (random() <= 0.5)				// Else, mix it up
			self->monsterinfo.currentmove = &insane_move_run_normal;
		else
			self->monsterinfo.currentmove = &insane_move_run_insane;
}


void insane_pain (edict_t *self, edict_t *other, float kick, int damage)
{
	int	l,r;

	if (level.time < self->pain_debounce_time)
		return;

	self->pain_debounce_time = level.time + 3;

	r = 1 + (rand()&1);
	if (self->health < 25)
		l = 25;
	else if (self->health < 50)
		l = 50;
	else if (self->health < 75)
		l = 75;
	else
		l = 100;
	gi.sound (self, CHAN_VOICE, gi.soundindex (va("player/male/pain%i_%i.wav", l, r)), 1, ATTN_IDLE, 0);

	if (skill->value == 3)
		return;		// no pain anims in nightmare

	// Don't go into pain frames if crucified.
	if (self->spawnflags & 8)
	{
		self->monsterinfo.currentmove = &insane_move_struggle_cross;			
		return;
	}
	
	if  ( ((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)) )
	{
		self->monsterinfo.currentmove = &insane_move_crawl_pain;
	}
	else
		self->monsterinfo.currentmove = &insane_move_stand_pain;

}

void insane_onground (edict_t *self)
{
	self->monsterinfo.currentmove = &insane_move_down;
}

void insane_checkdown (edict_t *self)
{
	if (self->spawnflags & 32)				// Always stand
		return;
	if (random() < 0.3)
	{
		if (random() < 0.5)
			self->monsterinfo.currentmove = &insane_move_uptodown;
		else
			self->monsterinfo.currentmove = &insane_move_jumpdown; 
	}
}

void insane_checkup (edict_t *self)
{
	// If Hold_Ground and Crawl are set
	if ( (self->spawnflags & 4) && (self->spawnflags & 16) )
		return;
	if (random() < 0.5)
		self->monsterinfo.currentmove = &insane_move_downtoup;				

}

void insane_stand (edict_t *self)
{
	if (self->spawnflags & 8)			// If crucified
	{
		self->monsterinfo.currentmove = &insane_move_cross;
		self->monsterinfo.aiflags |= AI_STAND_GROUND;
	}
	// If Hold_Ground and Crawl are set
	else if ( (self->spawnflags & 4) && (self->spawnflags & 16) )
		self->monsterinfo.currentmove = &insane_move_down;
	else
		if (random() < 0.5)
			self->monsterinfo.currentmove = &insane_move_stand_normal;
		else
			self->monsterinfo.currentmove = &insane_move_stand_insane;
}

void insane_dead (edict_t *self)
{
	if (self->spawnflags & 8)
	{
		self->flags |= FL_FLY;
	}
	else
	{
		VectorSet (self->mins, -16, -16, -24);
		VectorSet (self->maxs, 16, 16, -8);
		self->movetype = MOVETYPE_TOSS;
	}
	self->svflags |= SVF_DEADMONSTER;
	self->nextthink = 0;
	gi.linkentity (self);
}


void insane_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
	int		n;

	if (self->health <= self->gib_health)
	{
		gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_IDLE, 0);
		for (n= 0; n < 2; n++)
			ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
		for (n= 0; n < 4; n++)
			ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
		ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
		self->deadflag = DEAD_DEAD;
		return;
	}

	if (self->deadflag == DEAD_DEAD)
		return;

	gi.sound (self, CHAN_VOICE, gi.soundindex(va("player/male/death%i.wav", (rand()%4)+1)), 1, ATTN_IDLE, 0);

	self->deadflag = DEAD_DEAD;
	self->takedamage = DAMAGE_YES;

	if (self->spawnflags & 8)
	{
		insane_dead (self);
	}
	else
	{
		if ( ((self->s.frame >= FRAME_crawl1) && (self->s.frame <= FRAME_crawl9)) || ((self->s.frame >= FRAME_stand99) && (self->s.frame <= FRAME_stand160)) )		
			self->monsterinfo.currentmove = &insane_move_crawl_death;
		else
			self->monsterinfo.currentmove = &insane_move_stand_death;
	}
}


/*QUAKED misc_insane (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn CRAWL CRUCIFIED STAND_GROUND ALWAYS_STAND
*/
void SP_misc_insane (edict_t *self)
{
	if (deathmatch->value)
	{
		G_FreeEdict (self);
		return;
	}

	sound_fist = gi.soundindex ("insane/insane11.wav");
	sound_shake = gi.soundindex ("insane/insane5.wav");
	sound_moan = gi.soundindex ("insane/insane7.wav");
	sound_scream[0] = gi.soundindex ("insane/insane1.wav");
	sound_scream[1] = gi.soundindex ("insane/insane2.wav");
	sound_scream[2] = gi.soundindex ("insane/insane3.wav");
	sound_scream[3] = gi.soundindex ("insane/insane4.wav");
	sound_scream[4] = gi.soundindex ("insane/insane6.wav");
	sound_scream[5] = gi.soundindex ("insane/insane8.wav");
	sound_scream[6] = gi.soundindex ("insane/insane9.wav");
	sound_scream[7] = gi.soundindex ("insane/insane10.wav");

	self->movetype = MOVETYPE_STEP;
	self->solid = SOLID_BBOX;
	self->s.modelindex = gi.modelindex("models/monsters/insane/tris.md2");

	VectorSet (self->mins, -16, -16, -24);
	VectorSet (self->maxs, 16, 16, 32);

	self->health = 100;
	self->gib_health = -50;
	self->mass = 300;

	self->pain = insane_pain;
	self->die = insane_die;

	self->monsterinfo.stand = insane_stand;
	self->monsterinfo.walk = insane_walk;
	self->monsterinfo.run = insane_run;
	self->monsterinfo.dodge = NULL;
	self->monsterinfo.attack = NULL;
	self->monsterinfo.melee = NULL;
	self->monsterinfo.sight = NULL;
	self->monsterinfo.aiflags |= AI_GOOD_GUY;

	gi.linkentity (self);

	if (self->spawnflags & 16)				// Stand Ground
		self->monsterinfo.aiflags |= AI_STAND_GROUND;

	self->monsterinfo.currentmove = &insane_move_stand_normal;
	
	self->monsterinfo.scale = MODEL_SCALE;

	if (self->spawnflags & 8)					// Crucified ?
	{
		VectorSet (self->mins, -16, 0, 0);
		VectorSet (self->maxs, 16, 8, 32);
		self->flags |= FL_NO_KNOCKBACK;
		flymonster_start (self);
	}
	else
	{
		walkmonster_start (self);
		self->s.skinnum = rand()%3;
	}
}

