function hex_ai()
{	
	if state != "IDLE" && global.speedrun
		global.speedrun_timer++;
		
	switch(state)
	{
		case "IDLE":
			if hp < max_hp
			{
				if global.speedrun
				{
					timer_active = true;
					global.speedrun_timer = 0;
				}
				cnt = 0;
				roll_init();
				bgm_play("battle");
			}
			break;
		
		case "WAIT":
			cooldown -= global.time_scale;
			if cooldown <= 0
			{
				cooldown = 0;
				switch(current_attack)
				{
					case 0:
						cnt = 0;
						roll_init();
						break;
		
					case 1:
						cnt = 3;
						smash_init();
						break;
			
					case 2:
						cnt = 5;
						bounce_init();
						break;
			
					case 3:
						cnt = 2;
						spawn_init();
						break;
				}
			}
			break;
				
			
		case "ROLL":
		    rebounce_timer--;
    
		    var _roll_spd;
    
		    if abs(roll_angle + roll_spd) >= 60
		        _roll_spd = (60 - abs(roll_angle)) * sign(roll_angle);
		    else if sign(roll_angle) == -sign(roll_angle + roll_spd)
		        _roll_spd = -roll_angle;
		    else
		        _roll_spd = roll_spd;
    
		    if collision_line(x, y, x + 144 * sign(-_roll_spd), y, oParentSolid, false, false) != noone
		    && rebounce_timer <= 0
		    {
		        roll_spd  *= -1;
		        _roll_spd *= -1;
		        rebounce_timer = 10;
		        screen_shake(20);
        
		        ++cnt;
        
		        if cnt == 1
		            roll_acc *= -1;
		        if cnt == 3
		        {
		            cnt = 1;
		            smash_init();
		        }
		    }
    
		    if abs(roll_angle) == 60 || roll_angle == 0
		    {
		        roll_angle = 0;
		        y = base_y;
				
		        var _base_angle;
				if _roll_spd > 0
				    _base_angle = 240;
				else if _roll_spd < 0
				    _base_angle = 300;
				else
				    _base_angle = (roll_acc > 0) ? 240 : 300;
		        pivot_x = x + lengthdir_x(side_len, _base_angle);
		        pivot_y = y + lengthdir_y(side_len, _base_angle);
		    }
    
		    roll_angle += _roll_spd;
		    image_angle += _roll_spd;
    
		    var _current_angle = point_direction(pivot_x, pivot_y, x, y);
		    var _new_angle     = _current_angle + _roll_spd;
		    x = pivot_x + lengthdir_x(side_len, _new_angle);
		    y = pivot_y + lengthdir_y(side_len, _new_angle);
    
		    roll_spd += roll_acc;
    
		    break;
			
		case "SMASH_BEGIN":
			
			x += x_spd;
			y += y_spd;
			image_angle += 0.4 * spd;
			
			if y < target_y
			{
				state = "SMASH";
				
				image_angle = round(image_angle / 60) * 60;
				
				y_spd = 20;
				y_acc = 1;
				
				break;
			}
	
			spd += acc;
			x_spd = lengthdir_x(spd, dir);
			y_spd = lengthdir_y(spd, dir);
			
			break;
			
		case "SMASH":
			
			y += y_spd;
			
			if collision_line(x, y, x, y + 108 + y_spd, oParentSolid, false, false) != noone
			{
				while collision_line(x, y, x, y + 108, oParentSolid, false, false) == noone
					y++;
				
				hex_var_erase();
				
				screen_shake(20);
				
				if !--cnt
					current_attack = hex_pick_attack();
				else
					smash_init();
			}
			y_spd += y_acc;
			
			var _x_alter = global.player.x - x
			x += max(4, _x_alter / 200) * sign(_x_alter);
			
			break;
		
		case "SPAWN":
		
			image_angle += abs(y_spd);
			y += y_spd;
			
			if y_spd == 15
			{
				image_angle -= abs(y_spd);
				
				hex_var_erase();
				
				screen_shake(15);
				
				icd(oEnemyHex, x, 998, depth + 1);
				
				if !--cnt
					current_attack = hex_pick_attack();
				else
					spawn_init();
			}
			y_spd += y_acc;
			break;
		
		case "BOUNCE":
			
			if collision_line(x, y, x + 144 * sign(x_spd), y, oParentSolid, false, false) != noone
				x_spd = 0;
			
			if y_spd == 20
			{
				image_angle += facing * 9;
				hex_var_erase();
				
				screen_shake(15);
				
				if !--cnt
					current_attack = hex_pick_attack();
				else
					bounce_init();
					
				break;
			}
			
			image_angle += facing * 9;
			x += x_spd;
			y += y_spd;
			
			y_spd += y_acc;
			break;
		
	}
}
function roll_init()
{
    state = "ROLL";
	roll_spd = 5 * sign(global.player.x - x);
	roll_acc = -0.1 * sign(global.player.x - x);

    var _base_angle = (roll_spd > 0) ? 240 : 300;
    pivot_x = x + lengthdir_x(side_len, _base_angle);
    pivot_y = y + lengthdir_y(side_len, _base_angle);
}
function smash_init()
{
	state = "SMASH_BEGIN";
	target_x = clamp(global.player.x, 200, 1920 - 200 - 64);
	target_y = y - 480;

	dir = point_direction(x, y, target_x, target_y);
	spd = 15;
	acc = 0.3;
	
	x_spd = lengthdir_x(spd, dir);
	y_spd = lengthdir_y(spd, dir);
}
function spawn_init()
{
	y_spd = -15;
	y_acc = 0.6;
	
	state = "SPAWN";
}
function bounce_init()
{
	state = "BOUNCE";

	y_spd = -20;
	y_acc = 1;

	facing = sign(global.player.x - x);
	x_spd = facing * 9;
}

function hex_pick_attack()
{
	hex_var_erase();
	cooldown = _cooldown[global.difficulty];
	state = "WAIT";
	
    var _row = attack_matrix[last_attack];
    var _atk = weighted_pick(_row);
    
    if _atk == 3 && instance_number(oEnemyHex) > 1
    {
        var _fallback = array_create(array_length(_row));
		array_copy(_fallback, 0, _row, 0, array_length(_row));
		_fallback[3] = 0;
		_atk = weighted_pick(_fallback);
    }
    
    last_attack = _atk;
    return _atk;
}
function hex_var_erase()
{
	spd = 0;
	acc = 0;
	dir = 0;
	x_spd = 0;
	y_spd = 0;
	x_acc = 0;
	y_acc = 0;
	roll_spd = 0;
	roll_acc = 0;
	roll_angle = 0;
	
	y = base_y;
	image_angle = round(image_angle / 60) * 60;
}