I was working on a math based solution but it got more complicated quickly. I'll try your original approach again, give me a few hours 
Edit: got it:
Code: ags

Edit: got it:
// room script file
enum KiteState {
eKiteCircling, eKiteSwoopingIn, eKiteSwoopingOut
};
KiteState kite_state = eKiteCircling;
int exposed_timer;
int circling_timer;
int kite_region; // 0 = right, 1 = top right, etc.
function room_Load()
{
cKite.z = -60;
kite_region = 0;
}
void caught_by_kite() {
Display("Caught by kite");
// QuitGame(0);
}
bool kite_is_outside_screen() {
ViewFrame* vf = Game.GetViewFrame(cKite.NormalView, cKite.Loop, cKite.Frame);
int hw = Game.SpriteWidth[vf.Graphic] / 2;
int h = Game.SpriteHeight[vf.Graphic];
if (cKite.x < -hw || cKite.x > Game.Camera.Width + hw) return true;
return cKite.y < 0 || cKite.y > Game.Camera.Height + h;
}
function room_RepExec() {
// is player in danger
bool danger_zone = Region.GetAtRoomXY(player.x, player.y) == region[5];
if (danger_zone && cEgo.IsCollidingWithChar(cKite)) caught_by_kite(); //death script
oDanger.Visible = danger_zone; // obj currently being used for testing
exposed_timer = (exposed_timer + 1) * danger_zone; // increase / reset timer
if (kite_state == eKiteCircling) {
// kite swoops for player, continuing straight if player moves
if (exposed_timer > 100) {
exposed_timer = 0;
kite_state = eKiteSwoopingIn;
float dx = IntToFloat(player.x - cKite.x);
float dy = IntToFloat(player.y - cKite.y);
float f = 2000.0 / Maths.Sqrt(dx * dx + dy * dy);
cKite.Walk(cKite.x + FloatToInt(f * dx), cKite.y + FloatToInt(f * dy), eNoBlock, eAnywhere);
}
else {
circling_timer++;
if (circling_timer >= 50 && !cKite.Moving) {
kite_region = (kite_region + 1) % 8;
float a = (IntToFloat(-kite_region)) * (Maths.Pi / 4.0);
cKite.x = Game.Camera.Width / 2 + FloatToInt(IntToFloat(Game.Camera.Width) * Maths.Cos(a), eRoundNearest);
cKite.y = Game.Camera.Height / 2 + FloatToInt(IntToFloat(Game.Camera.Height) * Maths.Sin(a), eRoundNearest) - cKite.z;
circling_timer = 0;
// visible top left
if (kite_region == 3 && !cKite.Moving) {
cKite.x = 300;
cKite.y = -100 - cKite.z;
cKite.Walk(-300, 200 - cKite.z, eNoBlock, eAnywhere);
} // visible bottom right
if (kite_region == 7 && !cKite.Moving) {
cKite.x = Game.Camera.Width - 300;
cKite.y = Game.Camera.Height + 100 - cKite.z;
cKite.Walk(Game.Camera.Width + 300, Game.Camera.Height - 200 - cKite.z, eNoBlock, eAnywhere);
}
}
}
}
// this makes the kite stop as soon as it has left the screen
if (kite_state == eKiteSwoopingIn && !kite_is_outside_screen()) kite_state = eKiteSwoopingOut;
if (kite_state == eKiteSwoopingOut && kite_is_outside_screen()) {
kite_state = eKiteCircling;
float a = Maths.ArcTan2(IntToFloat(cKite.y - Game.Camera.Height / 2), IntToFloat(cKite.x - Game.Camera.Width / 2));
kite_region = (FloatToInt(-a * 4.0 / Maths.Pi, eRoundNearest) + 8) % 8;
}
}