#include "scripts/common.txt"

const array<int> BPGruntMeleeAnims = {anim_aiMelee2, anim_aiMelee3, anim_aiMelee4, anim_aiMelee5, anim_aiAltMelee1, anim_aiAltMelee2, anim_aiAltMelee3};
const array<int> BPGruntRangeAnims = {anim_aiRangeAttack1, anim_aiRangeAttack2, anim_aiRangeAttack3, anim_aiRangeAttack4,
										anim_aiRangeAttack5, anim_aiRangeAttack6, anim_aiRangeAttack7, anim_aiRangeAttack9, anim_aiRangeAttack10};

	//anim_aiRangeAttack10 - Shaman Powerup Speel Cast
	//anim_aiRangeAttack9 - Demon Attack (shoots fireball)
	//anim_aiRangeAttack7 - GunFire (Plasma guy fast crouch shot)
	//anim_aiRangeAttack6 - Tribal Dart1
	//anim_aiRangeAttack5 - GunFire (Plasma guy fast shot)
	//anim_aiRangeAttack4 - Heatseeking shaman spell cast
	//anim_aiRangeAttack3 - Grenade
	//anim_aiRangeAttack2 - GunFire
	//anim_aiRangeAttack1 - Shaman Spell Attack
	//anim_aiMelee2-5
	//anim_aiAltMelee1
	//anim_aiAltMelee2 - Double Swing
	//anim_aiAltMelee3 -  BackFist
	//anim_aiTeleportIn - Shaman Teleport up from ground
	//anim_aiTeleportOut - Shaman Begin Teleporting
	//hanging - anim_special_event01

	//fx 133 - bubble lightning shot
	//fx 244 - lots of blood
	//fx 247 - long hunter heat seeking boomrang
	//fx 254 - plant attack
	//fx 256 - slow demon fireball
	//fx 257 - fast demon fireball
	//fx 258 - fastest demon fireball

class TurokBPGrunt : TurokBPEnemy {
	// int fxIndex = 239;
	// int delayFrames = 0;
	float meleeRange = 110.0f;
	float minAttackDelay = 1.0f; //in seconds
	float maxAttackDelay = 3.0f; //in seconds
	
	float curAttackTime = 0.0f;
	//------------------------------------------------------------------------------------------------------------------------
    TurokBPGrunt(kActor @actor) {
        super(actor);
    }
	//------------------------------------------------------------------------------------------------------------------------
	void OnTickStart() {
		TurokBPEnemy::OnTickStart();
		SetModelTextures();
		//SetModelCloak();
		curAttackTime = Math::RandRange(minAttackDelay, maxAttackDelay);
		if (Game.GetCurrentMapID() == 53) {
			PlayAnimation(anim_aiTeleportIn);
		}

		// self.Flags() |= AF_STATIONARY;
		// self.Flags() |= AF_INVINCIBLE;
		//self.Health() += 200;
	}
	//------------------------------------------------------------------------------------------------------------------------
    // void OnTick() {
		// // uint16 buttons = Player.Buttons();
		// // float x = 150.0f;
		// // float y = 0.0f;
		// // float z = 150.0f;
		// // if (delayFrames <= 0) {
			// // if ((buttons & (BC_MAPZOOMOUT)) != 0) {
				// // fxIndex = Math::Max(fxIndex - 1, 1);
				// // self.SpawnFx("fx/generic_" + fxIndex + ".kfx", kVec3(x, y, z));
				// // Game.PrintLine("generic " + fxIndex, 0, 60);
				// // delayFrames = 10;
			// // }
			// // if ((buttons & (BC_MAPZOOMIN)) != 0) {
				// // fxIndex = Math::Min(fxIndex + 1, 260);
				// // self.SpawnFx("fx/generic_" + fxIndex + ".kfx", kVec3(x, y, z));
				// // Game.PrintLine("generic " + fxIndex, 0, 60);
				// // delayFrames = 10;
			// // }
		// // }
		// // delayFrames--;
		
		// TurokBPEnemy::OnTick();
		
		// if (IsDead()) {
			// return;
		// }
		
		// AIStandard();
	// }
	//------------------------------------------------------------------------------------------------------------------------
	bool CanUpdateAI() {
		if (self.AnimState().PlayingID() == anim_aiTeleportIn) {
			self.CastToAI().AIFlags() |= AIF_NOTHINK;
			if (self.AnimState().CycleCompleted()) {
				self.CastToAI().AIFlags() &= ~AIF_NOTHINK;
			} else {
				return false;
			}
		}
		return true;
	}
	//------------------------------------------------------------------------------------------------------------------------
	void AIStandard(bool useRange = false) {
		if (!HasTarget()) {
			return;
		}
		
		kVec3 targetPos = self.GetTarget().Origin();
		
		if (!IsAttacking()) {
			curAttackTime = Math::Maxf(curAttackTime - GAME_DELTA_TIME, 0.0f);
		}
		
		if (CanAttack()) {
			curAttackTime = Math::RandRange(minAttackDelay, maxAttackDelay);
			float targetDist = Math::Sqrt(self.DistanceToPoint(targetPos));
			if (targetDist <= meleeRange) {
				PlayRandomAnimation(BPGruntMeleeAnims);
			} else if (useRange) {
				OnRangeAttack();
			}
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
	void OnRangeAttack() {
		PlayRandomAnimation(BPGruntRangeAnims);
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool CanAttack() {
		return (!IsAttacking() and curAttackTime <= 0);
	}
	//------------------------------------------------------------------------------------------------------------------------
	bool IsAttacking() {
		int animID = self.AnimState().PlayingID();
		if (BPGruntMeleeAnims.find(animID) >= 0) {
			return true;
		}
		if (BPGruntRangeAnims.find(animID) >= 0) {
			return true;
		}
		return false;
	}
	//------------------------------------------------------------------------------------------------------------------------
    void FootStepPuff(kActor @instigator, const float a, const float x, const float y, const float z) {
    }
	//------------------------------------------------------------------------------------------------------------------------
    void HighPriestSpellAttack(kActor @instigator, const float w, const float x, const float y, const float z) {
        if(self.GetTarget() is null) {
            return;
        }
        self.SpawnFx("fx/spellcast.kfx", kVec3(x, y, z));
    }
	//------------------------------------------------------------------------------------------------------------------------
    void HighPriestSpellSound(kActor @instigator, const float w, const float x, const float y, const float z) {
        self.PlaySound("sounds/shaders/high_priest_spell_attack.ksnd");
    }
	//------------------------------------------------------------------------------------------------------------------------
    void SwooshTrail1(kActor @instigator, const float w, const float x, const float y, const float z) {
        switch (self.ModelVariation()) {
			case GV_GENERIC_AXE:
			case GV_DEMON_AXE:
				self.RenderModel().AddTrailEffect("Trail_Axe", 17);
				break;
				
			case GV_GENERIC_CLUB:
			case GV_SHAMAN:
				self.RenderModel().AddTrailEffect("Trail_Mace", 17);
				break;
			
			case GV_COMMANDER_SPEAR:
			case GV_WARRIOR_SPEAR:
			case GV_DEMON_SPEAR:
				self.RenderModel().AddTrailEffect("Trail_Pole1", 17);
				break;
				
			case GV_COMMANDER_RIFLE1:
			case GV_COMMANDER_RIFLE2:
			case GV_COMMANDER_RIFLE3:
			case GV_COMMANDER_RIFLE4:
			case GV_POACHER_RIFLE:
			case GV_CYBORG_PULSE_RIFLE:
				self.RenderModel().AddTrailEffect("Trail_Shotgun", 17);
				break;
				
			case GV_POACHER_KNIFE:
				self.RenderModel().AddTrailEffect("Trail_Sword", 17);
				break;
				
			case GV_POACHER_PISTOL1:
			case GV_POACHER_PISTOL2:
				self.RenderModel().AddTrailEffect("Trail_Pistol", 17);
				break;
				
			case GV_POACHER_SHOTGUN:
				self.RenderModel().AddTrailEffect("Trail_Shotgun", 17);
				break;
				
			case GV_WARRIOR_BONE:
				self.RenderModel().AddTrailEffect("Trail_Bone", 17);
				break;
				
			case GV_WARRIOR_DART:
				self.RenderModel().AddTrailEffect("Trail_DartGun", 17);
				break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void GunFire(kActor @instigator, const float w, const float x, const float y, const float z) {
        if (self.GetTarget() is null) {
            return;
        }

		if (onGunFire !is null) {
			onGunFire(@this, @instigator, w, x, y, z);
			return;
		}
        
		if (Game.GetCurrentMapID() == 53) {
			self.SpawnFx("fx/ponly_spellcast.kfx", kVec3(x, y, z));
			return;
		}
		
        if (self.ModelVariation() == GV_COMMANDER_RIFLE4 || self.ModelVariation() == GV_CYBORG_PULSE_RIFLE) {
            self.PlaySound("sounds/shaders/machine_gun_shot_2.ksnd");
            self.SpawnProjectile("fx/enemy_longhunter.kfx", kVec3(x, y, z), self.GetTarget().Origin(), Math::Deg2Rad(45.0f));
            return;
        }
        
        self.PlaySound("sounds/shaders/generic_8_enemy_human_gunfire.ksnd");
        self.SpawnProjectile("fx/enemy_bullet.kfx", kVec3(x, y, z), self.GetTarget().Origin(), Math::Deg2Rad(45.0f));
    }
	//------------------------------------------------------------------------------------------------------------------------
    void ThrowGrenade(kActor @instigator, const float w, const float x, const float y, const float z) {
        self.SpawnFx("fx/generic_114.kfx", kVec3(x, y, z));
    }
	//------------------------------------------------------------------------------------------------------------------------
    void DemonAttack(kActor @instigator, const float w, const float x, const float y, const float z) {
        if (self.GetTarget() is null) {
            return;
        }
        
        self.SpawnProjectile("fx/generic_256.kfx", kVec3(x, y, z), self.GetTarget().Origin(), Math::Deg2Rad(45.0f));
    }
	//------------------------------------------------------------------------------------------------------------------------
    void TribalDart1(kActor @instigator, const float w, const float x, const float y, const float z)
    {
		if (Game.GetCurrentMapID() == 53) {
			self.SpawnFx("fx/generic_178.kfx", kVec3(x, y, z)); //raptor missle
			return;
		}
		
        if(self.GetTarget() is null)
        {
            return;
        }
        
        self.SpawnFx("fx/generic_193.kfx", kVec3(x, y, z));
    }
	//------------------------------------------------------------------------------------------------------------------------
    void TribalDart2(kActor @instigator, const float w, const float x, const float y, const float z)
    {
		if (Game.GetCurrentMapID() == 53) {
			self.SpawnProjectile("fx/enemy_plasma1.kfx", kVec3(x, y, z), self.GetTarget().Origin(), Math::Deg2Rad(45.0f));
			return;
		}
        self.SpawnFx("fx/generic_194.kfx", kVec3(x, y, z));
    }
	//------------------------------------------------------------------------------------------------------------------------
    void DeathSound(kActor @instigator, const float w, const float x, const float y, const float z) {
        if (self.ModelVariation() >= GV_CYBORG_PULSE_RIFLE && self.ModelVariation() <= GV_CYBORG_SPEAR) {
            self.PlaySound("sounds/shaders/ancient_warrior_death.ksnd");
            return;
        }
        else if (self.ModelVariation() >= GV_DEMON_AXE && self.ModelVariation() <= GV_DEMON_LORD) {
            switch(Math::RandMax(3)) {
				case 0:
					self.PlaySound("sounds/shaders/demon_death_scream_1.ksnd");
					break;
				case 1:
					self.PlaySound("sounds/shaders/demon_death_scream_2.ksnd");
					break;
				case 2:
					self.PlaySound("sounds/shaders/demon_death_scream_3.ksnd");
					break;
            }
            return;
        }
        
        switch(Math::RandMax(3)) {
			case 0:
				self.PlaySound("sounds/shaders/human_death_scream_1.ksnd");
				break;
			case 1:
				self.PlaySound("sounds/shaders/human_death_scream_2.ksnd");
				break;
			case 2:
				self.PlaySound("sounds/shaders/human_death_scream_3.ksnd");
				break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void InjurySound(kActor @instigator, const float w, const float x, const float y, const float z) {
        if (self.ModelVariation() >= GV_CYBORG_PULSE_RIFLE && self.ModelVariation() <= GV_CYBORG_SPEAR) {
            self.PlaySound("sounds/shaders/ancient_warrior_death.ksnd");
            return;
        }
        else if (self.ModelVariation() >= GV_DEMON_AXE && self.ModelVariation() <= GV_DEMON_LORD) {
            switch(Math::RandMax(3)) {
				case 0:
					self.PlaySound("sounds/shaders/demon_effort_injury_grunt_1.ksnd");
					break;
				case 1:
					self.PlaySound("sounds/shaders/demon_effort_injury_grunt_2.ksnd");
					break;
				case 2:
					self.PlaySound("sounds/shaders/demon_effort_injury_grunt_3.ksnd");
					break;
            }
            return;
        }
        
        switch(Math::RandMax(3)) {
			case 0:
				self.PlaySound("sounds/shaders/human_effort_injury_grunt_1.ksnd");
				break;
			case 1:
				self.PlaySound("sounds/shaders/human_effort_injury_grunt_2.ksnd");
				break;
			case 2:
				self.PlaySound("sounds/shaders/human_effort_injury_grunt_3.ksnd");
				break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void ViolentSound(kActor @instigator, const float w, const float x, const float y, const float z) {
        if (self.ModelVariation() >= GV_CYBORG_PULSE_RIFLE && self.ModelVariation() <= GV_CYBORG_SPEAR) {
            self.PlaySound("sounds/shaders/ancient_warrior_death.ksnd");
            return;
        }
        else if (self.ModelVariation() >= GV_DEMON_AXE && self.ModelVariation() <= GV_DEMON_LORD) {
            switch (Math::RandMax(3)) {
				case 0:
					self.PlaySound("sounds/shaders/demon_violent_death_1.ksnd");
					break;
				case 1:
					self.PlaySound("sounds/shaders/demon_violent_death_2.ksnd");
					break;
				case 2:
					self.PlaySound("sounds/shaders/demon_violent_death_3.ksnd");
					break;
            }
            return;
        }
        
        switch (Math::RandMax(3)) {
			case 0:
				self.PlaySound("sounds/shaders/human_violent_death_1.ksnd");
				break;
			case 1:
				self.PlaySound("sounds/shaders/human_violent_death_2.ksnd");
				break;
			case 2:
				self.PlaySound("sounds/shaders/human_violent_death_3.ksnd");
				break;
        }
    }
	//------------------------------------------------------------------------------------------------------------------------
    void SetModelUnCloak() {
        kRenderModel @model = self.RenderModel();
        if (model !is null) {
			model.SetModel("models/dyn_human_grunt01.bin", "anims/dyn_human_grunt01_anim.bin");
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
    void SetModelCloak() {
        kRenderModel @model = self.RenderModel();
        if (model !is null) {
			model.SetModel("models/dyn_human_cloak_grunt01.bin", "anims/dyn_human_grunt01_anim.bin");
		}
	}
	//------------------------------------------------------------------------------------------------------------------------
    void SetModelTextures() {
        kRenderModel @model = self.RenderModel();
        if (model !is null) {
			if (self.ModelVariation() >= GV_CYBORG_PULSE_RIFLE && self.ModelVariation() <= GV_CYBORG_SPEAR) {
				self.ImpactType() = IT_METAL;
			}
			
			switch(self.ModelVariation())
			{
				// common soldier
				case GV_GENERIC:
				case GV_GENERIC_AXE:
				case GV_GENERIC_CLUB:
					// face
					model.SetTexture(19, Math::SysRand() % 12);
					break;
				
				// commander
				case GV_COMMANDER_SPEAR:
				case GV_COMMANDER_RIFLE1:
				case GV_COMMANDER_RIFLE2:
				case GV_COMMANDER_RIFLE3:
				case GV_COMMANDER_RIFLE4:
					// chest
					model.SetTexture(0, 1);
					model.SetTexture(9, 1);
					
					// arms
					model.SetTexture(10, 1);
					model.SetTexture(11, 1);
					model.SetTexture(12, 1);
					model.SetTexture(13, 1);
					model.SetTexture(14, 1);
					model.SetTexture(15, 1);
					model.SetTexture(16, 1);
					model.SetTexture(17, 1);
					
					// face
					model.SetTexture(19, Math::SysRand() % 12);
					break;
					
				// poacher
				case GV_POACHER_KNIFE:
				case GV_POACHER_PISTOL1:
				case GV_POACHER_PISTOL2:
				case GV_POACHER_RIFLE:
				case GV_POACHER_SHOTGUN:
					// chest
					model.SetTexture(0, 5);
					model.SetTexture(9, 5);
					
					// legs
					model.SetTexture(1, 2);
					model.SetTexture(3, 2);
					model.SetTexture(4, 2);
					model.SetTexture(5, 2);
					model.SetTexture(7, 2);
					model.SetTexture(8, 2);
					
					// shin
					model.SetTexture(2, 2);
					model.SetTexture(6, 2);
					
					// face
					//model.SetTexture(19, 6);
					model.SetTexture(19, Math::SysRand() % 6);
					//model.SetTexture(19, Math::SysRand() % 12);
					break;
					
				// warrior
				case GV_WARRIOR_BONE:
				case GV_WARRIOR_DART:
				case GV_WARRIOR_SPEAR:
					// hands
					model.SetTexture(17, 2);
					
					// chest
					model.SetTexture(0, 2);
					model.SetTexture(9, 2);
					
					// arms
					model.SetTexture(10, 2);
					model.SetTexture(11, 2);
					model.SetTexture(12, 2);
					model.SetTexture(13, 2);
					model.SetTexture(14, 2);
					model.SetTexture(15, 2);
					model.SetTexture(16, 2);
					
					// neck
					model.SetTexture(18, 1);
					break;
					
				// shaman
				case GV_SHAMAN:
					// chest
					model.SetTexture(0, 3);
					model.SetTexture(9, 3);
					
					// neck
					model.SetTexture(18, 2);
					
					// legs
					model.SetTexture(1, 1);
					model.SetTexture(3, 1);
					model.SetTexture(4, 1);
					model.SetTexture(5, 1);
					model.SetTexture(7, 1);
					model.SetTexture(8, 1);
					
					// shin
					model.SetTexture(2, 1);
					model.SetTexture(6, 1);
					
					// hands
					model.SetTexture(17, 3);
					
					// arms
					model.SetTexture(10, 3);
					model.SetTexture(11, 3);
					model.SetTexture(12, 3);
					model.SetTexture(13, 3);
					model.SetTexture(14, 3);
					model.SetTexture(15, 3);
					model.SetTexture(16, 3);
					break;
					
				// cyborg guard
				case GV_CYBORG_PULSE_RIFLE:
					// legs
					model.SetTexture(1, 1);
					model.SetTexture(3, 1);
					model.SetTexture(4, 1);
					model.SetTexture(5, 1);
					model.SetTexture(7, 1);
					model.SetTexture(8, 1);
					
					// shin
					model.SetTexture(2, 1);
					model.SetTexture(6, 1);
					
					// chest
					model.SetTexture(0, 4);
					model.SetTexture(9, 4);
					
					// arms
					model.SetTexture(10, 4);
					model.SetTexture(11, 4);
					model.SetTexture(12, 4);
					model.SetTexture(13, 4);
					model.SetTexture(14, 4);
					model.SetTexture(15, 4);
					model.SetTexture(16, 4);
					
					// neck
					model.SetTexture(18, 3);
					break;
					
				// demon
				case GV_DEMON_AXE:
				case GV_DEMON_SPEAR:
				case GV_DEMON_HANDS:
					// hands
					model.SetTexture(17, 6);
					model.SetTexture(13, 6);
					
					// legs
					model.SetTexture(1, 2);
					model.SetTexture(3, 2);
					model.SetTexture(4, 2);
					model.SetTexture(5, 2);
					model.SetTexture(7, 2);
					model.SetTexture(8, 2);
					
					// shin
					model.SetTexture(2, 2);
					model.SetTexture(6, 2);
					
					// chest
					model.SetTexture(0, 6);
					model.SetTexture(9, 6);
					
					// arms
					model.SetTexture(10, 6);
					model.SetTexture(11, 6);
					model.SetTexture(12, 6);
					model.SetTexture(13, 6);
					model.SetTexture(14, 6);
					model.SetTexture(15, 6);
					model.SetTexture(16, 6);
					
					// neck
					model.SetTexture(18, 4);
					break;
					
				// demon lord
				case GV_DEMON_LORD:
					// hands
					model.SetTexture(17, 7);
					model.SetTexture(13, 7);
					
					// legs
					model.SetTexture(1, 3);
					model.SetTexture(3, 3);
					model.SetTexture(4, 3);
					model.SetTexture(5, 3);
					model.SetTexture(7, 3);
					model.SetTexture(8, 3);
					
					// shin
					model.SetTexture(2, 3);
					model.SetTexture(6, 3);
					
					// chest
					model.SetTexture(0, 7);
					model.SetTexture(9, 7);
					
					// arms
					model.SetTexture(10, 7);
					model.SetTexture(11, 7);
					model.SetTexture(12, 7);
					model.SetTexture(13, 7);
					model.SetTexture(14, 7);
					model.SetTexture(15, 7);
					model.SetTexture(16, 7);
					
					// neck
					model.SetTexture(18, 5);
					break;
			}
		}
		
	}
	//------------------------------------------------------------------------------------------------------------------------
};
