////////////////////////////////////////////////////
// Distance Functions                             //
////////////////////////////////////////////////////

// Returns the distance from (x1, y1) to (x2, y2)
function Distance(x1, y1, x2, y2){
  return ((x1-x2)^2 + (y1-y2)^2)^0.5;
}

// Returns the distance from the given point to the player.
function DistanceFromPlayer(x, y){
  return Distance(x, y, GetPlayerX, GetPlayerY);
}

// Returns the distance from the given point to the boss.
function DistanceFromBoss(x, y){
  return Distance(x, y, GetEnemyX, GetEnemyY);
}

////////////////////////////////////////////////////
// Angle Functions                                //
////////////////////////////////////////////////////

// Returns the angle from (x1, y1) to (x2, y2)
function AngleFrom(x1, y1, x2, y2){
  return atan2(y2-y1, x2-x1);
}

// Returns the angle from the player to the given point.
function AngleFromPlayer(x, y){
  return AngleFrom(GetPlayerX, GetPlayerY, x, y);
}

// Returns the angle from the given point to the player.
function AngleToPlayer(x, y){
  return AngleFrom(x, y, GetPlayerX, GetPlayerY);
}

// Returns the angle from the boss to the given point.
function AngleFromBoss(x, y){
  return AngleFrom(GetEnemyX, GetEnemyY, x, y);
}

// Returns the angle from the given point to the boss.
function AngleToBoss(x, y){
  return AngleFrom(x, y, GetEnemyX, GetEnemyY);
}

// Returns the equivalent angle between 0 and 360, not including 360 (i.e. converts 540 to 180)
function NormalizeAngle(angle){
  angle %= 360;
  if(angle<0){ angle += 360; }
  return angle;
}

// Returns true if the angles are equal (i.e. an angle of 360 is equal to an angle of 0).
// Otherwise it returns false. Using IsEqual instead of AreEqual because of Danmakufu
// naming conventions.
function IsSameAngle(angle1, angle2){
  angle1 = NormalizeAngle(angle1);
  angle2 = NormalizeAngle(angle2);
  return angle1 == angle2;
}

// Returns the shortest angular distance between two angles.
// Example: the shortest angular distance between 330 and -90 is 60
function AngularDistance(angle1, angle2){
  let distance = NormalizeAngle(angle2 - angle1);
  if(distance>180){ distance-=360; }
  return distance; 
}

////////////////////////////////////////////////////
// Effect Functions                               //
////////////////////////////////////////////////////

// Creates an effect like a bullet's delay but does not fire a bullet.
function CreateDelayEffect(x, y, color, duration){
  CreateShotA(255, x, y, duration);
  SetShotDataA(255, 0, 500, 0, 0, 0, 0, color);
  SetShotKillTime(255, 0);
  FireShot(255);
}

////////////////////////////////////////////////////
// String Functions                               //
////////////////////////////////////////////////////

// Truncates a number into an integer and converts it to a string.
function IntString(number){
  let str = ToString(number);
  let str2 = "";
  let i = 0;
  while (str[i] != '.'){
    str2 = str2 ~ [str[i]];
    i++;
  }
  return(str2); 
}

////////////////////////////////////////////////////
// Information Functions                          //
////////////////////////////////////////////////////

// Returns the lower of the two numbers.
function lower(num1, num2){
  if(num1 < num2){
    return num1;
  }
  else {
    return num2;
  }
}

// Returns the greater of the two numbers.
function upper(num1, num2){
  if(num1 > num2){
    return num1;
  }
  else {
    return num2;
  }
}

////////////////////////////////////////////////////
// Object Functions                               //
////////////////////////////////////////////////////

function ObjShot_Create(x, y, speed, angle, graphic, delay){
  let obj = Obj_Create(OBJ_SHOT);
  Obj_SetPosition(obj, x, y);
  Obj_SetSpeed(obj, speed);
  Obj_SetAngle(obj, angle);
  ObjShot_SetGraphic(obj, graphic);
  ObjShot_SetDelay(obj, delay);
  return obj;
}

function ObjEffect_InitializeRect(texture, layer){
  let obj = Obj_Create(OBJ_EFFECT);
  ObjEffect_SetTexture(obj, texture);
  ObjEffect_SetLayer(obj, layer);
  ObjEffect_SetPrimitiveType(obj, PRIMITIVE_TRIANGLEFAN);
  ObjEffect_CreateVertex(obj, 4);
  return obj;
}
function ObjEffect_SetXYRect(id, left, top, right, bottom){
  ObjEffect_SetVertexXY(id, 0, left, top);
  ObjEffect_SetVertexXY(id, 1, right, top);
  ObjEffect_SetVertexXY(id, 2, right, bottom);
  ObjEffect_SetVertexXY(id, 3, left, bottom);
}
function ObjEffect_SetUVRect(id, left, top, right, bottom){
  ObjEffect_SetVertexUV(id, 0, left, top);
  ObjEffect_SetVertexUV(id, 1, right, top);
  ObjEffect_SetVertexUV(id, 2, right, bottom);
  ObjEffect_SetVertexUV(id, 3, left, bottom);
}
function ObjEffect_SetColor(id, vertexes, a, r, g, b){
  ascent(i in 0..vertexes){
    ObjEffect_SetVertexColor(id, i, a, r, g, b);
  }
}

////////////////////////////////////////////////////
// Miscellaneous Functions                        //
////////////////////////////////////////////////////

function IsFocused {
  return GetKeyState(VK_SLOWMOVE)==KEY_PUSH || GetKeyState(VK_SLOWMOVE)==KEY_HOLD;
}

function GetPlayerMoveAngle {
  let angle = NULL;
  if(GetKeyState(VK_DOWN)==KEY_HOLD){
    if(GetKeyState(VK_RIGHT)==KEY_HOLD){
      angle = 45;
    }
    else if(GetKeyState(VK_LEFT)==KEY_HOLD){
      angle = 135;
    }
    else {
      angle = 90;
    }
  }
  else if(GetKeyState(VK_UP)==KEY_HOLD){
    if(GetKeyState(VK_RIGHT)==KEY_HOLD){
      angle = 315;
    }
    else if(GetKeyState(VK_LEFT)==KEY_HOLD){
      angle = 225;
    }
    else {
      angle = 270;
    }
  }
  else if(GetKeyState(VK_RIGHT)==KEY_HOLD){
    angle = 0;
  }
  else if(GetKeyState(VK_LEFT)==KEY_HOLD){
    angle = 180;
  }
  return angle;
}


function GetPointToLineSegment(cx, cy, ax, ay, bx, by){

  let distanceLine;
  let distanceSegment;

  let r_numerator = (cx-ax)*(bx-ax) + (cy-ay)*(by-ay);
  let r_denomenator = (bx-ax)*(bx-ax) + (by-ay)*(by-ay);
  let r = r_numerator / r_denomenator;
  
  let px = ax + r*(bx-ax);
  let py = ay + r*(by-ay);
  
  let s =  ((ay-cy)*(bx-ax)-(ax-cx)*(by-ay) ) / r_denomenator;
  
  let distanceLine = absolute(s)*(r_denomenator^0.5);
  
  let xx = px;
  let yy = py;
  if (r>=0 && r<=1){
    distanceSegment = distanceLine;
  }
  else {
    let dist1 = (cx-ax)*(cx-ax) + (cy-ay)*(cy-ay);
    let dist2 = (cx-bx)*(cx-bx) + (cy-by)*(cy-by);
    if(dist1 < dist2){
      xx = ax;
      yy = ay;
      distanceSegment = dist1^0.5;
    }
    else {
      xx = bx;
      yy = by;
      distanceSegment = dist2^0.5;
    }
  }
  return distanceSegment;

}

function IsPointInRectangle(x, y, left, top, right, bottom){
  if(x<left || x>right || y<top || y>bottom){
    return false;
  }
  else {
    return true;
  }
}