Events.PlayerMeleeActionCallback m_playerMeleeActionEvent = null;
Events.UserMessageCallback m_userMessageCallback = null;
IPlayer dick;
Vector2 punchAreaOffset = new Vector2(1,1);
Vector2 punchArea = new Vector2(75,75);
Vector2 kickArea = new Vector2(75,75);
Vector2 speed_x = new Vector2(25,0);
Vector2 speed_y = new Vector2(0,17);
bool roundStartMessageIsMuted = false;

public void OnStartup() {

	//no need to check that ALL settings load correctly. Checking the first one will suffice.
	if (!Game.LocalStorage.TryGetItemFloat("FLY_punchAreaX", out punchArea.X)){ 
		resetSettings();
	} else {
		Game.LocalStorage.TryGetItemFloat("FLY_punchAreaY", out punchArea.Y);
		Game.LocalStorage.TryGetItemFloat("FLY_kickAreaX", out kickArea.X);
		Game.LocalStorage.TryGetItemFloat("FLY_kickAreaY", out kickArea.Y);
		Game.LocalStorage.TryGetItemFloat("FLY_speed_x", out speed_x.X);
		Game.LocalStorage.TryGetItemFloat("FLY_speed_y", out speed_y.Y);
		Game.LocalStorage.TryGetItemBool("FLY_roundStartMessageIsMuted", out roundStartMessageIsMuted);
	}

	IPlayer[] players = Game.GetPlayers();

	//For every player...
	for(int playerCounter=0; playerCounter < players.Length; playerCounter++){
		//If the start-round-message is enabled...
		if(!roundStartMessageIsMuted){
			//If they're a moderator...
			IUser playerUser = players[playerCounter].GetUser();
			if (playerUser.IsModerator){
				//Show the message.
				Game.ShowChatMessage("Fly: Run '/fly help' for config options.", Color.Green, playerUser.UserIdentifier);
			}
		}
	}

	//start listeners
	m_userMessageCallback = Events.UserMessageCallback.Start(OnUserMessage);
	m_playerMeleeActionEvent = Events.PlayerMeleeActionCallback.Start(OnPlayerMeleeAction);
}

public void OnPlayerMeleeAction(IPlayer plr, PlayerMeleeHitArg[] args) {
	Area area = new Area(new Vector2(0,0), new Vector2(0,0));
	if((plr.IsMeleeAttacking || plr.IsJumpAttacking) && plr.IsWalking){
		Vector2 plrpos = plr.GetWorldPosition();
		int a = plr.FacingDirection;

		if (plr.IsCrouching){
			//Full area punch
			area = new Area(plrpos - punchArea, plrpos + punchArea);
		} else {
			//Punch only what's in front of the player
			if (plr.FacingDirection == 1) {
				area = new Area(plrpos + punchAreaOffset, plrpos + punchArea);
			} else {
				area = new Area(plrpos - punchArea, plrpos - punchAreaOffset);
			}
		}
		


		IObject[] Obj = Game.GetObjectsByArea(area);
		foreach(IObject obj in Obj){
			if(obj.GetBodyType() != BodyType.Static){
				try{
					dick = (IPlayer)obj;
					
				}
				catch{
					Vector2 ojbpos = obj.GetWorldPosition();
					Game.PlayEffect("DIG", ojbpos);
					obj.SetLinearVelocity(Vector2.Multiply(speed_x, new Vector2((float)a,0)));
				}
			}
		}
	}
	else if((plr.IsKicking || plr.IsJumpKicking) && plr.IsWalking){
			Vector2 plrpos = plr.GetWorldPosition();

			IObject[] Obj = Game.GetObjectsByArea(new Area(plrpos - kickArea, plrpos + kickArea));
			
			foreach(IObject obj in Obj){
				if(obj.GetBodyType() != BodyType.Static){
					try{
						dick = (IPlayer)obj;
					}
					catch{
						if (plr.IsCrouching){
							//Cool particles
							Game.PlayEffect("DestroyPaper", plrpos - new Vector2(0, -5));

							//Fly with the object beneath us
							plr.SetLinearVelocity(speed_y);
						}
							Vector2 ojbpos = obj.GetWorldPosition();
							Game.PlayEffect("WS", ojbpos);

							//Make the objects fly
							obj.SetLinearVelocity(speed_y);

					}
				}
			}
		}
 }

public void OnUserMessage(UserMessageCallbackArgs args) {

	if (args.IsCommand){
		if(args.Command == "FLY"){
			if(args.User.IsModerator){
				string[] a = args.CommandArguments.Split();
				switch(a[0]){
					case "help":
						try{
							Game.ShowChatMessage("Fly command list:", Color.Yellow, args.User.UserIdentifier);
							Game.ShowChatMessage("/fly speed_x <25/50> - to change horizontal speed", Color.Yellow, args.User.UserIdentifier);
							Game.ShowChatMessage("/fly speed_y <17/34> - to change vertical speed", Color.Yellow, args.User.UserIdentifier);
							Game.ShowChatMessage("/fly punch_area <75/150> <75/150> - to change the punch area-of-effect" , Color.Yellow);
							Game.ShowChatMessage("/fly kick_area <75/150> <75/150> - to change the kick area-of-effect", Color.Yellow, args.User.UserIdentifier);
							Game.ShowChatMessage("/fly settings - to view current settings.", Color.Yellow, args.User.UserIdentifier);
							Game.ShowChatMessage("/fly default - to restore to default settings. Run this if the script isn't working.", Color.Yellow, args.User.UserIdentifier);
							Game.ShowChatMessage("/fly toggle message - to toggle the round-start message.", Color.Yellow, args.User.UserIdentifier);
							
						} catch{}
					break;
					case "FLY_speed_x":
						try{
							//change setting
							speed_x.X = (float)Convert.ToInt32(a[1]);
							//add change to storage
							Game.LocalStorage.SetItem("FLY_speed_x", speed_x.X);

							Game.ShowChatMessage("Horizontal speed has been set to " + speed_x.X, Color.Green, args.User.UserIdentifier);
						} catch{}
					break;

					case "FLY_speed_y":
						try{
							//change setting
							speed_y.Y = (float)Convert.ToInt32(a[1]);
							//add change to storage
							Game.LocalStorage.SetItem("FLY_speed_y", speed_y.Y);

							Game.ShowChatMessage("Vertical speed has been set to " + speed_y.Y, Color.Green, args.User.UserIdentifier);
						} catch{}
					break;
					case "punch_area":
						try{
							//change settings
							punchArea.X = (float)Convert.ToInt32(a[1]);
							punchArea.Y = (float)Convert.ToInt32(a[2]);
							//add change to storage
							Game.LocalStorage.SetItem("FLY_punchAreaX", punchArea.X);
							Game.LocalStorage.SetItem("FLY_punchAreaY", punchArea.Y);

							Game.ShowChatMessage("Punch area set to: " + punchArea.X + " " + punchArea.Y, Color.Green, args.User.UserIdentifier);
						} catch{}
					break;
					case "kick_area":
						try{
							//change setting
							kickArea.X = (float)Convert.ToInt32(a[1]);
							kickArea.Y = (float)Convert.ToInt32(a[2]);

							//add change to storage
							Game.LocalStorage.SetItem("FLY_kickAreaX", kickArea.X);
							Game.LocalStorage.SetItem("FLY_kickAreaY", kickArea.Y);

							Game.ShowChatMessage("Kick area set to: " + kickArea.X + " " + kickArea.Y, Color.Green, args.User.UserIdentifier);
						} catch{}
					break;
					case "settings":
						Game.ShowChatMessage("punch_area = " + punchArea.X + " " + punchArea.Y, Color.Yellow, args.User.UserIdentifier);
						Game.ShowChatMessage("kick_area = " + kickArea.X + " " + kickArea.Y, Color.Yellow, args.User.UserIdentifier);
						Game.ShowChatMessage("speed_x = " + speed_x.X, Color.Yellow, args.User.UserIdentifier);
						Game.ShowChatMessage("speed_y = " + speed_y.Y, Color.Yellow, args.User.UserIdentifier);
						Game.ShowChatMessage("roundStartMessageIsMuted = " + roundStartMessageIsMuted.ToString(), Color.Yellow, args.User.UserIdentifier);
					break;
					case "default":
						resetSettings();

						Game.ShowChatMessage("Fly settings have been reset to default.", Color.Green, args.User.UserIdentifier);
					break;
					case "toggle":
						if (a[1] == "message"){
							try{
								//change settings
								roundStartMessageIsMuted = !roundStartMessageIsMuted;
								//add change to storage
								Game.LocalStorage.SetItem("FLY_roundStartMessageIsMuted", roundStartMessageIsMuted);

								Game.ShowChatMessage("FLY: The round start reminder has been toggled.", Color.Green, args.User.UserIdentifier);
							} catch{}
						} else {
							Game.ShowChatMessage("FLY: That command does not exist.", Color.Red, args.User.UserIdentifier);
						}
					break;
				}
			} else {
				Game.ShowChatMessage("FLY: ERROR - " + args.User.Name + "/" + args.User.AccountID + ":" + args.User.AccountName + " is not a moderator!", Color.Red, args.User.UserIdentifier);   
			}
		}

	}
}

public void resetSettings(){
	punchArea = new Vector2(75,75);
	kickArea = new Vector2(75,75);
	speed_x = new Vector2(25,0);
	speed_y = new Vector2(0,17);
	roundStartMessageIsMuted = false;

	Game.LocalStorage.SetItem("FLY_punchAreaX", punchArea.X);
	Game.LocalStorage.SetItem("FLY_punchAreaY", punchArea.Y);
	Game.LocalStorage.SetItem("FLY_kickAreaX", kickArea.X);
	Game.LocalStorage.SetItem("FLY_kickAreaY", kickArea.Y);
	Game.LocalStorage.SetItem("FLY_speed_x", speed_x.X);
	Game.LocalStorage.SetItem("FLY_speed_y", speed_y.Y);
	Game.LocalStorage.SetItem("FLY_roundStartMessageIsMuted", roundStartMessageIsMuted);
}