/*==============================================================================
XMAS Elf - From Twisted Christmas Mod by Twisted Matrix
==============================================================================*/

// (000 - 007) Rocking back and forth on feet
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8

// (008 - 017) Skipping! (Running)
$frame skip1 skip2 skip3 skip4 skip5 skip6 skip7 skip8
$frame skip9 skip10

// (018 - 029) Walking
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8
$frame walk9 walk10 walk11 walk12

// (030 - 036) Suprise, jump up into the air with legs wide apart
$frame surprise1 surprise2 surprise3 surprise4 surprise5 surprise6 surprise7

// (037 - 048) ATTACK - Swing cane around (long version)
$frame magic1 magic2 magic3 magic4 magic5 magic6 magic7 magic8
$frame magic9 magic10 magic11 magic12

// (049 - 056) ATTACK - Jump up and smash cane into ground
$frame jump1 jump2 jump3 jump4 jump5 jump6 jump7 jump8

// (057 - 061) ATTACK - Swing cane around (short version)
$frame attack1 attack2 attack3 attack4 attack5

// (062 - 066) PAIN - Recoil backward
$frame pain1 pain2 pain3 pain4 pain5

// (067 - 078) ATTACK - Fall downward with cane infront
$frame ambush1 ambush2 ambush3 ambush4 ambush5 ambush6 ambush7 ambush8
$frame ambush9 ambush10 ambush11 ambush12

// (079 - 093) DEATH - Backward
$frame bdeath1 bdeath2 bdeath3 bdeath4 bdeath5 bdeath6 bdeath7 bdeath8
$frame bdeath9 bdeath10 bdeath11 bdeath12 bdeath13 bdeath14 bdeath15

// (094 - 107) DEATH - Forward
$frame death1 death2 death3 death4 death5 death6 death7 death8
$frame death9 death10 death11 death12 death13 death14

// (108 - 109) Misc modelling stuff
$frame base1 base2

//======================================================================
void() elf_stand1 = [ $stand1, elf_stand2 ] {monster_idle_sound();ai_stand();};
void() elf_stand2 = [ $stand2, elf_stand3 ] {ai_stand();};
void() elf_stand3 = [ $stand3, elf_stand4 ] {ai_stand();};
void() elf_stand4 = [ $stand4, elf_stand5 ] {ai_stand();};
void() elf_stand5 = [ $stand5, elf_stand6 ] {ai_stand();};
void() elf_stand6 = [ $stand6, elf_stand7 ] {ai_stand();};
void() elf_stand7 = [ $stand7, elf_stand8 ] {ai_stand();};
void() elf_stand8 = [ $stand8, elf_stand1 ] {ai_stand();};

//======================================================================
void() elf_walk1 = [ $walk1, elf_walk2 ] {monster_idle_sound();ai_walk(10);};
void() elf_walk2 = [ $walk2, elf_walk3 ] {ai_walk(6);};
void() elf_walk3 = [ $walk3, elf_walk4 ] {monster_footstep(FALSE);ai_walk(4);};
void() elf_walk4 = [ $walk4, elf_walk5 ] {ai_walk(0);};
void() elf_walk5 = [ $walk5, elf_walk6 ] {ai_walk(2);};
void() elf_walk6 = [ $walk6, elf_walk7 ] {ai_walk(3);};

void() elf_walk7 = [ $walk7, elf_walk8 ] {ai_walk(10);};
void() elf_walk8 = [ $walk8, elf_walk9 ] {ai_walk(6);};
void() elf_walk9 = [ $walk9, elf_walk10 ] {monster_footstep(FALSE);ai_walk(4);};
void() elf_walk10 = [ $walk10, elf_walk11 ] {ai_walk(0);};
void() elf_walk11 = [ $walk11, elf_walk12 ] {ai_walk(2);};
void() elf_walk12 = [ $walk12, elf_walk1 ] {ai_walk(3);};

//======================================================================
void() elf_run1 = [ $skip1, elf_run2 ] {monster_idle_sound();ai_run(1);};
void() elf_run2 = [ $skip2, elf_run3 ] {ai_run(6);};
void() elf_run3 = [ $skip3, elf_run4 ] {ai_run(20);};
void() elf_run4 = [ $skip4, elf_run5 ] {monster_footstep(FALSE);ai_run(12);};
void() elf_run5 = [ $skip5, elf_run6 ] {ai_run(8);};

void() elf_run6 = [ $skip6, elf_run7 ] {ai_run(1);};
void() elf_run7 = [ $skip7, elf_run8 ] {ai_run(6);};
void() elf_run8 = [ $skip8, elf_run9 ] {ai_run(20);};
void() elf_run9 = [ $skip9, elf_run10 ] {monster_footstep(FALSE);ai_run(12);};
void() elf_run10 = [ $skip10, elf_run1 ] {ai_run(8);};

//======================================================================
void() elf_slide1 = [ $surprise1, elf_slide2 ] {ai_run_slide(2);monster_idle_sound();};
void() elf_slide2 = [ $surprise2, elf_slide3 ] {ai_run_slide(4);};
void() elf_slide3 = [ $surprise3, elf_slide4 ] {ai_run_slide(6);};
void() elf_slide4 = [ $surprise4, elf_slide5 ] {ai_run_slide(6);};
void() elf_slide5 = [ $surprise5, elf_slide6 ] {ai_run_slide(4);};
void() elf_slide6 = [ $surprise6, elf_slide7 ] {ai_run_slide(3);};
void() elf_slide7 = [ $surprise7, elf_run1 ] {ai_run(2);};

//======================================================================
// ELF 2 - SPRAY MAGIC (Range)
//======================================================================
void(float sideang) elf_shot =
{
	local	vector org, ang, dir, avel;
	
	if (!self.enemy) return;
	if (self.health < 1) return;
		
	// Flash effect to show where projectile is coming from	
	self.effects = self.effects | EF_MUZZLEFLASH;
	if (sideang < 0) sound (self, CHAN_WEAPON, "xmas/elf/attack1.wav", 1, ATTN_NORM);

	makevectors (self.angles);	
	org = self.origin + attack_vector(self.attack_offset);

	// Create elevation angle and use makevectors to create projectile direction
	ang = vectoangles(self.enemy.origin - org);
	ang_x = -self.attack_elev;	// Negative = upwards angle 
	makevectors (ang);
	// fire magic in arc pattern (sideang)
	dir = (v_forward + v_right * sideang) * SPEED_ELF;	

	avel = vecrand(100,200,FALSE);
	Launch_Grenade(org, dir, avel, CT_PROJ_ELF);
};

//----------------------------------------------------------------------
void() elf_magic1 = [ $magic12, elf_magic2 ] {
	sound(self, CHAN_WEAPON, "xmas/elf/magic.wav", 1, ATTN_NORM);};
void() elf_magic2 = [ $magic11, elf_magic3 ] {ai_face();};
void() elf_magic3 = [ $magic10, elf_magic4 ] {ai_face();};
void() elf_magic4 = [ $magic9, elf_magic5 ] {ai_face();};
void() elf_magic5 = [ $magic8, elf_magic6 ] {ai_face();
	self.attack_elev = SUB_Elevation(ELEV_DEFAULT, self.origin, self.enemy.origin, SPEED_ELF); };
void() elf_magic6 = [ $magic7, elf_magic7 ] {ai_face();
	self.attack_elev = SUB_Elevation(self.attack_elev, self.origin, self.enemy.origin, SPEED_ELF); };
void() elf_magic7 = [ $magic6, elf_magic8 ] {ai_face();
	self.attack_elev = SUB_Elevation(self.attack_elev, self.origin, self.enemy.origin, SPEED_ELF); };
void() elf_magic8 = [ $magic5, elf_magic9 ] {elf_shot(-0.1);};
void() elf_magic9 = [ $magic4, elf_magic10 ] {elf_shot(0);};
void() elf_magic10 = [ $magic3, elf_magic11 ] {elf_shot(0.1);};
void() elf_magic11 = [ $magic2, elf_magic12 ] {};
void() elf_magic12 = [ $magic1, elf_run1 ] {};

//======================================================================
// ELF 1 - SWING CANE - Both elf types can swing cane if within range
//======================================================================
void() elf_melee =
{
	local float ldmg;

	if (!self.enemy) return;
	if (self.health < 1) return;
		
	ai_charge(10);
	ai_damagebreakable(10);
	if (!ai_checkmelee(MONAI_MELEEELF)) return;

	// Can the target bleed?
	if (!self.enemy.takedamage) return;

	if (random() < 0.5) sound(self, CHAN_VOICE, "xmas/elf/cane_hit1.wav", 1, ATTN_NORM);
	else sound(self, CHAN_VOICE, "xmas/elf/cane_hit2.wav", 1, ATTN_NORM);

	// Cane Impact (damage 1-9) is very weak
	ldmg = (random() + random() + random()) * 3;
	if (ldmg < 1) ldmg = 1;
	T_Damage (self.enemy, self, self, ldmg, DAMARMOR);

	// Spawn blood at cane of elf
	spawn_touchblood (self, self.enemy, ldmg*3);
}

//----------------------------------------------------------------------
void() elf_cane1 = [ $attack1, elf_cane2 ] {ai_charge(5);
	if (random() < 0.5) sound(self, CHAN_WEAPON, "xmas/elf/cane_swipe1.wav", 1, ATTN_NORM);
	else sound(self, CHAN_WEAPON, "xmas/elf/cane_swipe2.wav", 1, ATTN_NORM);	
};
void() elf_cane2 = [ $attack2, elf_cane3 ] {ai_charge(5);};
void() elf_cane3 = [ $attack3, elf_cane4 ] {elf_melee();};
void() elf_cane4 = [ $attack4, elf_cane5 ] {};
void() elf_cane5 = [ $attack5, elf_run1 ] {
	if (ai_checkmelee(MONAI_MELEEELF) && self.enemy.health > 0) {
		if (self.health > 0) self.think = elf_cane1;
	}
};

//======================================================================
// ELF 1 - JUMP FUNCTION (range)
//======================================================================
void()	Elf_JumpTouch =
{
	local	float	ldmg;

	if (self.health <= 0) return;
	ai_jumpbreakable(20);			// Damage any breakables
	self.touch = SUB_Null;			// No more touching
	self.count = self.count + 1;	// Total amount of touch jumps
	self.think = self.th_jumpexit;	// Exit frame
	self.jumptouch = other;			// Keep track of touch target

	// Do not damage other elves with jump attacks
	// Prevents packs from killing themselves
	if (self.classtype != other.classtype && other.takedamage) {
		if ( vlen(self.velocity) > 300 ) {
			ldmg = 5 + 5*random();
			T_Damage (other, self, self, ldmg, DAMARMOR);	
			// Spawn some touch blood (no explicit direction)
			spawn_touchblood (self.enemy, self.enemy, ldmg*3);
		}
	}

	// Is the elf floating in the air?
	if (!checkbottom(self)) {
		// Is the elf standing on something?		
		if (self.flags & FL_ONGROUND) {	
			// Do an extra jump if got the count
			if (self.count < 2)  self.think = self.th_jump;
		}
	}

	// Next timer
	self.nextthink = time + 0.1;
};

//----------------------------------------------------------------------------
void() elf_leap1 =[ $jump1, elf_leap2 ] {ai_face();
	self.jump_flag = time + MONAI_JUMPTIMEOUT; // Stop jumping so much
	if (random() < 0.5) sound(self, CHAN_WEAPON, "xmas/elf/jump1.wav", 1, ATTN_NORM);
	else sound(self, CHAN_WEAPON, "xmas/elf/jump2.wav", 1, ATTN_NORM);
};
void() elf_leap2 =[ $jump2, elf_leap3 ] {ai_face();};
void() elf_leap3 =[ $jump3, elf_leap4 ] {
	ai_face();
	self.jump_flag = time + MONAI_JUMPTIMEOUT; // Stop jumping so much
	self.touch = Elf_JumpTouch;
	makevectors (self.angles);
	self.velocity = v_forward * MONAI_JUMPELFDIST + '0 0 200';
	self.origin_z = self.origin_z + 4;
	self.flags = self.flags - (self.flags & FL_ONGROUND);
	self.oldorigin = self.origin;
};
void() elf_leap4 =[ $jump4, elf_leap5 ] {};
void() elf_leap5 =[ $jump5, elf_leap6 ] {};
void() elf_leap6 =[ $jump6, elf_leap7 ] {
	// Double check monster is still falling?
	if (CheckZeroVector(self.velocity) || self.oldorigin == self.origin) {
		self.ideal_yaw = random() * 360; //random jump angle
		self.think = elf_leap3;
	}
	self.oldorigin = self.origin;
};

//----------------------------------------------------------------------
void() elf_leap7 =[ $jump7, elf_leap8] {monster_footstep(FALSE);};
void() elf_leap8 =[ $jump8, elf_run1] {ai_resetangles();};

//======================================================================
// Elven Pain!
//======================================================================
void() elf_pain1 = [ $pain1, elf_pain2 ] {};
void() elf_pain2 = [ $pain2, elf_pain3 ] {};
void() elf_pain3 = [ $pain3, elf_pain4 ] {};
void() elf_pain4 = [ $pain4, elf_pain5 ] {};
void() elf_pain5 = [ $pain5, elf_run1 ] {};

//----------------------------------------------------------------------
void(entity inflictor, entity attacker, float damage) elf_pain =
{
	// Check all pain conditions and set up what to do next
	monster_pain_check(attacker, damage);

	// Any pain animation/sound required?
	if (self.pain_check > 0) {
		sound (self, CHAN_VOICE, self.pain_sound, 1, ATTN_NORM);
		if (self.pain_check == 1) elf_pain1 ();
		else if (self.pain_check == 2) {
			// reset axe hit and setup short pain recovery
			self.axhitme = 0;
			self.pain_finished = time + 1;
			elf_pain1 ();
		}
	}
};

//======================================================================
// Typical forward/backward death animation
//======================================================================
void() elf_die1 =[ $death1, elf_die2] {};
void() elf_die2 =[ $death2, elf_die3] {monster_check_gib();};
void() elf_die3 =[ $death3, elf_die4] {monster_check_gib();
	self.solid = SOLID_NOT;};
void() elf_die4 =[ $death4, elf_die5] {};
void() elf_die5 =[ $death5, elf_die6] {};
void() elf_die6 =[ $death6, elf_die7] {
	// Drop metal cane sound
	sound (self, CHAN_WEAPON, GIB_SOUND_METALA, 1, ATTN_NORM);
};
void() elf_die7 =[ $death7, elf_die8] {};
void() elf_die8 =[ $death8, elf_die9] {monster_death_postcheck();};
void() elf_die9 =[ $death9, elf_die9] {monster_deadbody_check();};

//----------------------------------------------------------------------
void() elf_dieb1 =[ $bdeath1, elf_dieb2] {};
void() elf_dieb2 =[ $bdeath2, elf_dieb3] {monster_check_gib();};
void() elf_dieb3 =[ $bdeath3, elf_dieb4] {monster_check_gib();
	self.solid = SOLID_NOT;};
void() elf_dieb4 =[ $bdeath4, elf_dieb5] {};
void() elf_dieb5 =[ $bdeath5, elf_dieb6] {};
void() elf_dieb6 =[ $bdeath6, elf_dieb7] {};
void() elf_dieb7 =[ $bdeath7, elf_dieb8] {};
void() elf_dieb8 =[ $bdeath8, elf_dieb9] {ai_back(4);monster_death_postcheck();};
void() elf_dieb9 =[ $bdeath9, elf_dieb9] {monster_deadbody_check();};

//----------------------------------------------------------------------
void() elf_die =
{
	// Sync cane to elf skin
	self.gib1skin = self.exactskin;

	// Pre-check routine to tidy up extra entities
	monster_death_precheck();

	// regular death
	if (!self.gibbed) {
		// Pick a random death sound
		if (random() > 0.5)
			sound (self, CHAN_VOICE, self.death_sound, 1, ATTN_NORM);
		else 
			sound (self, CHAN_VOICE, self.death_sound2, 1, ATTN_NORM);

		// Pick a random fall direction
		if (random() > 0.5) elf_die1 ();
		else elf_dieb1 ();
	}
};

/*======================================================================
QUAKED monster_xmas_elf (1 0 0) (-16 -16 -24) (16 16 16) Ambush
======================================================================*/
void() monster_xmas_elf =
{
	if (deathmatch) { remove(self); return; }

	self.mdl = "progs/xmas/mon_elf.mdl";		// Crazy Grinning Fool
	self.headmdl = "progs/xmas/h_elf.mdl";		// Shrunken Head
	self.gib1mdl = "progs/xmas/gib_elfcane.mdl";// Candy Cane
	self.gib1sound = GIB_IMPACT_METALA;
	
	precache_model (self.mdl);
	precache_model (self.headmdl);				// Grinning Pointy Hat
	precache_model (self.gib1mdl);				// Sugar Cane
	precache_model (MODEL_PROJ_ELF);			// Magic ice
	
	// Idle calm/angry
	self.idle_sound = "xmas/elf/idle.wav";		// Lots of giggling
	precache_sound (self.idle_sound);

	// Many different sight sounds (2 is very annoying)
	self.sight_sound = "xmas/elf/sight1.wav";	// Snarling sound
	self.sight_sound2 = "xmas/elf/sight2.wav";	// DIE HUMAN!?!
	self.sight_sound3 = "xmas/elf/sight3.wav";	// Screams
	self.sight_sound4 = "xmas/elf/sight4.wav";	// Screams
	precache_sound (self.sight_sound);
	precache_sound (self.sight_sound2);
	precache_sound (self.sight_sound3);
	precache_sound (self.sight_sound4);
	self.sight_count = 4;

	// Elf 1 - Melee/Jump attacks - cane impacts
	precache_sound ("xmas/elf/cane_swipe1.wav");
	precache_sound ("xmas/elf/cane_swipe2.wav");
	precache_sound ("xmas/elf/cane_hit1.wav");
	precache_sound ("xmas/elf/cane_hit2.wav");
	precache_sound ("xmas/elf/jump1.wav");
	precache_sound ("xmas/elf/jump2.wav");
	
	// Elf 2 - Magic attacks
	precache_sound ("xmas/elf/magic.wav");
	precache_sound ("xmas/elf/attack1.wav");
	precache_sound ("xmas/elf/miss.wav");
	
	// precache sight, pain and death (changes on type)
	self.pain_sound = "xmas/elf/pain.wav";
	self.death_sound = "xmas/elf/death1.wav";
	self.death_sound2 = "xmas/elf/death2.wav";
	precache_sound (self.pain_sound);
	precache_sound (self.death_sound);
	precache_sound (self.death_sound2);
	
	if (self.spawnflags & MON_ELF_MAGIC) {
		if (self.health < 1) self.health = 75;
		self.gibhealth = -25;
		self.th_missile = elf_magic1;
		self.exactskin = 2;
	}
	else {
		if (self.health < 1) self.health = 30;
		self.gibhealth = -20;
		self.th_jump = elf_leap1;
		self.th_jumpexit = elf_leap7;
		// pick a random one instead
		if (self.exactskin < 0 || self.exactskin > 1) self.exactskin = 0;
		if (self.exactskin == 0 && random() < 0.5) self.exactskin = 1;
	}
	
	self.solid = SOLID_NOT;				// No interaction with world
	self.movetype = MOVETYPE_NONE;		// Static item, no movement
	if (self.bboxtype < 1) self.bboxtype = BBOX_TINY;
	self.gibbed = FALSE;				// Still in one peice
	self.blockudeath = TRUE;			// No humanoid death sound
	self.pain_flinch = 10;				// Light pain threshold
	self.steptype = FS_TYPELIGHT;		// Very light feet
	self.meleeoffset = '20 0 20';		// Cane attack offset
	self.attack_offset = '10 0 4';		// Magic attack offset
	self.poisonous = FALSE;				// Not Supported
	self.deathstring = " was torn to pieces by a Elf\n";

	// Always reset Ammo Resistance to be consistent
	self.resist_shells = self.resist_nails = 0;
	self.resist_rockets = self.resist_cells = 0;
	
	self.th_checkattack = ElfCheckAttack;
	self.th_stand = elf_stand1;
	self.th_walk = elf_walk1;
	self.th_run = elf_run1;
	self.th_melee = elf_cane1;
	self.th_slide = elf_slide1;
	self.th_pain = elf_pain;
	self.th_die = elf_die;

	self.classtype = CT_MONELF;
	self.classgroup = CG_XMAS;
	self.classmove = MON_MOVEWALK;

	monster_start();
};