package entity;

import java.awt.Rectangle;

import core.*;
import enemyAI.enemyCommander;

public class harvester extends solidObject{
	 
	public vector iDirectionBody, jDirectionBody, kDirectionBody;
	
	public static vector cargoCenter;
	public vector cargoCenterClone;
	public int cargoAngle = 360;
	
	public static vector pillarCenter;
	public vector pillarCenterClone;
	public int pillarAngle = 360;

	public int unloadingCount;
	
	public static polygon3D[]  body, drill0, drill1, drill2, cargo, pillars;
	
	public int drillIndex = 2;
	public int drillingCount;
	
	public polygon3D[] bodyClone, drillClone0, drillClone1, drillClone2, cargoClone, pillarsClone;
	
	
	public static int maxHP = 260;
	
	// a screen space boundary which is used to test if the harvester object is
	// visible from camera point of view
	public final static Rectangle visibleBoundary = new Rectangle(-70, -25,screen_width+140, screen_height+85);

	// a screen space boundary which is used to test if the entire harvester
	// object is within the screen
	public final static Rectangle screenBoundary = new Rectangle(40, 40, screen_width-90,screen_height-80);

	// a screen space boundary which is used to test if the vision polygon of
	// the object is visible.
	public final static Rectangle visionBoundary = new Rectangle(0, 0, 1400+(screen_width-768),1300+(screen_height-512));
	
	public final static int visionW = 500 + (screen_width-768);
	public final static int visionH = 650 + (screen_height-512);
	
	//a bitmap representation of the vision of the harvester for enemy commander
	public static boolean[] bitmapVisionForEnemy; 
		
	//the oreintation of the harvester
	public int bodyAngle;
	
	//destination angle
	public int destinationAngle; 
			
	public static Rect border, destinationBlock, probeBlock, pointBlock;
	
	public goldMine myGoldMine;
	public refinery myRefinery;
	public int[] miningPositions;
	public int cargoDeposite;
	
	public int myMiningPosition;
	public int myDropPosition;
	public float insideRefineryPositionX;
	public float insideRefineryPositionY;
	
	
	public int jobStatus = 0;
	public final int idle = 0;
	public final int isDrilling = 1;
	public final int headingToMine=2;
	public final int returningToRefinery = 3;
	public final int unloadingCargo = 4;
	public final int enteringRefinery = 5;
	public final int leavingRefinery = 6;
	public final int facingGoldMine = 7;
	public final int facingRefinery = 8;
	public final int facingRight = 9; 
	public final int facingDownward = 10;
	
	public int waitingCount = 0;
	
	
	public int heuristicRecalculationCountDown;
	public byte[] heuristicMap;
	public boolean pathIsFound;
	public float nextNodeX, nextNodeY;	
	public int bodyTurnRate = 5;  
	
	public boolean insideRefinery;
	
	public boolean isEvadingFromAttack;
				

	public harvester(vector origin, int bodyAngle, int teamNo){
		speed = 0.008f;
		start = new vector(0,0,0);
		centre = origin.myClone();
		tempCentre = origin.myClone();
		this.bodyAngle = bodyAngle;
		immediateDestinationAngle = bodyAngle;
		progressStatus = 0;
		attackStatus = isAttacking;   
		miningPositions = new int[8];
		
		destinationAngle = bodyAngle;
		this.teamNo = teamNo;
		currentHP = maxHP;
		type = 2;  
		if(bitmapVisionForEnemy == null){
			bitmapVisionForEnemy = createBitmapVision(6);
		}
		
		
		ID = globalUniqID++;
		randomNumber = gameData.getRandom();
		height = centre.y + 0.5f;  //?
		theAssetManager = mainThread.theAssetManager; 
		boundary2D = new Rect((int)(origin.x*64) - 8, (int)(origin.z*64) + 8, 16, 16);
		border = new Rect(0,0,16,16);
		movement = new vector(0,0,0);
		updateOccupiedTiles(boundary2D.x1, boundary2D.y1);
		
		
		boundary2D.owner = this;
		destinationBlock = new Rect((int)(origin.x*64) - 8, (int)(origin.z*64) + 8, 16, 16);
		probeBlock = new Rect((int)(origin.x*64) - 6, (int)(origin.z*64) + 6, 12, 12);
		pointBlock = new Rect((int)(origin.x*64) - 6, (int)(origin.z*64) + 6, 12, 12);
		
		//create main axis in object space
		iDirection = new vector(1f,0,0);   
		jDirection = new vector(0,1f,0);   
		kDirection = new vector(0,0,1f);  
		
		//create polygons 
		makePolygons();
		
		heuristicMap = new byte[128 * 128];
	}
	
	public void makePolygons(){
		

		int skinTextureIndex = 23;
		
		if(body == null){
				
			body = new polygon3D[52];
			v = new vector[]{put(-0.071, 0.025, 0.11), put(-0.071, 0.025, -0.15), put(-0.071, 0.005, -0.15), put(-0.071, -0.025, -0.08), put(-0.071, -0.025, 0.07), put(-0.071, 0.005, 0.11)};
			body[0] = new polygon3D(v, put(-0.071, 0.027, 0.11), put(-0.071, 0.027, -0.15), put(-0.071, -0.025, 0.11), mainThread.textures[3], 1,1,1);
			
			v = new vector[]{put(0.071, 0.005, 0.11), put(0.071, -0.025, 0.07), put(0.071, -0.025, -0.08), put(0.071, 0.005, -0.15), put(0.071, 0.025, -0.15), put(0.071, 0.025, 0.11)};
			body[1] = new polygon3D(v, put(0.071, 0.027, -0.15),put(0.071, 0.027, 0.11), put(0.071, -0.025, -0.15), mainThread.textures[3], 1,1,1);
		
			v = new vector[]{put(-0.07, 0.04, -0.15), put(0.07, 0.04, -0.15), put(0.07, 0.015, -0.15), put(-0.07, 0.015, -0.15)};
			body[2] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[skinTextureIndex], 1,0.3f,1);
			
			v = new vector[]{put(-0.07, 0.005, -0.15), put(-0.04, 0.005, -0.15), put(-0.04, -0.025, -0.08), put(-0.07, -0.025, -0.08)};
			body[3] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[3], 1,1,1);
			
			v = new vector[]{put(-0.07, 0.015, -0.15), put(-0.04, 0.015, -0.15), put(-0.04, 0.005, -0.15), put(-0.07, 0.005, -0.15)};
			body[4] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[3], 1,1,1);
			
			v = new vector[]{put(0.04, 0.015, -0.15), put(0.07, 0.015, -0.15), put(0.07, 0.005, -0.15), put(0.04, 0.005, -0.15)};
			body[5] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[3], 1,1,1);
			
			v = new vector[]{put(0.04, 0.005, -0.15), put(0.07, 0.005, -0.15), put(0.07, -0.025, -0.08), put(0.04, -0.025, -0.08)};
			body[6] = new polygon3D(v, v[0], v[1], v [3], mainThread.textures[3], 1,1,1);
			
			v = new vector[]{put(0.07, 0.04, -0.15),  put(0.07, 0.04, 0.11), put(0.07, 0.015, 0.11),put(0.07, 0.015, -0.15)};
			body[7] = new polygon3D(v, put(0.07, 0.04, -0.15), put(0.07, 0.04, 0.11), put(0.07, 0.015, -0.15), mainThread.textures[skinTextureIndex], 1,0.3f,1);
			
			v = new vector[]{put(-0.07, 0.04, 0.11), put(-0.07, 0.04, -0.15), put(-0.07, 0.015, -0.15), put(-0.07, 0.015, 0.11)};
			body[8] = new polygon3D(v, put(-0.07, 0.04, 0.11), put(-0.07, 0.04, -0.15), put(-0.07, 0.015, 0.11), mainThread.textures[skinTextureIndex], 1,0.3f,1);
			
			v = new vector[]{put(0.07, 0.04, 0.11), put(-0.07, 0.04, 0.11), put(-0.07, 0.01, 0.11), put(0.07, 0.01, 0.11)};
			body[9] = new polygon3D(v, v[2], v[3], v [1], mainThread.textures[skinTextureIndex], 1,0.3f,1);
			
			v = new vector[]{put(0.07, 0.04, 0.11), put(-0.07, 0.04, 0.11), put(-0.07, 0.01, 0.11), put(0.07, 0.01, 0.11)};
			body[10] = new polygon3D(v, v[2], v[3], v [1], mainThread.textures[skinTextureIndex], 1,0.3f,1);
			
			v = new vector[]{put(0.07, 0.04, 0.11), put(0.07, 0.04, -0.15), put(-0.07, 0.04, -0.15),put(-0.07, 0.04, 0.11)};
			body[11] = new polygon3D(v, v[1], v[2], v[0], mainThread.textures[skinTextureIndex], 1,2f,1);
			body[11].shadowBias = 1000;
			
			v = new vector[]{put(-0.07, 0.12, 0.07), put(-0.07, 0.12, 0.02), put(-0.07, 0.04, 0.02), put(-0.07, 0.04, 0.11), put(-0.07, 0.07, 0.11)};
			body[12] = new polygon3D(v, put(-0.07, 0.12, 0.11), put(-0.07, 0.12, 0.02), put(-0.07, 0.04, 0.11), mainThread.textures[skinTextureIndex], 0.7f,0.7f,1);
			
			v = new vector[]{put(0, 0.07, 0.11), put(0, 0.04, 0.11), put(0, 0.04, 0.02), put(0, 0.12, 0.02), put(0, 0.12, 0.07)};
			body[13] = new polygon3D(v, put(0, 0.12, 0.02), put(0, 0.12, 0.11), put(0, 0.04, 0.02), mainThread.textures[skinTextureIndex], 0.7f,0.7f,1);
			
			v = new vector[]{put(-0.07, 0.12, 0.02), put(0.07, 0.12, 0.02), put(0.07, 0.04, 0.02), put(-0.07, 0.04, 0.02)};
			body[14] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1,0.7f,1);
			
			v = new vector[]{put(0, 0.07, 0.11 ), put(-0.07, 0.07, 0.11 ), put(-0.07, 0.04, 0.11 ), put(0, 0.04, 0.11 )};
			body[15] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.5f,1);
			
			v = new vector[]{put(0, 0.12, 0.02), put(-0.07, 0.12, 0.02), put(-0.07, 0.12, 0.07), put(0, 0.12, 0.07)};
			body[16] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.5f,1);
			
			v= new vector[]{put(0, 0.12, 0.07), put(-0.07, 0.12, 0.07), put(-0.07, 0.07, 0.11), put(0, 0.07, 0.11)};
			body[17] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[24], 1f,1f,1);
			body[17].shadowBias = 40000;
			
			v = new vector[]{put(-0.07, 0.04, 0.02), put(0.07, 0.04, 0.02), put(0.07, 0.12, 0.02), put(-0.07, 0.12, 0.02)};
			body[18] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1,0.7f,1);
			
			v = new vector[]{put(0.07, 0.12, 0.02),put(0.07, 0.15, 0.04), put(0.07, 0.16, 0.10), put(0.07, 0.15, 0.10), put(0.07, 0.12, 0.07)};
			body[19] = new polygon3D(v, put(0.07, 0.12, 0.02), put(0.07, 0.12, 0.13), put(0.07, 0.02, 0.02), mainThread.textures[skinTextureIndex], 1, 1,1);
			
			v = new vector[]{put(0, 0.12, 0.07), put(0, 0.15, 0.10), put(0, 0.16, 0.10),put(0, 0.15, 0.04),put(0, 0.12, 0.02) };
			body[20] = new polygon3D(v, put(0, 0.12, 0.13),put(0, 0.12, 0.02),  put(0, 0.02, 0.13), mainThread.textures[skinTextureIndex], 1, 1,1);
			
			v = new vector[]{put(0, 0.15, 0.04), put(0.07, 0.15, 0.04), put(0.07, 0.12, 0.02), put(0, 0.12, 0.02)};
			body[21] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.25f,1);
			
			v = new vector[]{put(0, 0.16, 0.10), put(0.07, 0.16, 0.10), put(0.07, 0.15, 0.04), put(0, 0.15, 0.04) };
			body[22] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.5f,1);
			
			v = new vector[]{put(0, 0.12, 0.02),put(0, 0.15, 0.04), put(0, 0.16, 0.10), put(0, 0.15, 0.10), put(0, 0.12, 0.07)};
			body[23] = new polygon3D(v, put(0, 0.12, 0.02), put(0, 0.12, 0.13), put(0, 0.02, 0.02), mainThread.textures[skinTextureIndex], 1, 1,1);
			
			v = new vector[]{put(0.07, 0.12, 0.07), put(0.07, 0.15, 0.10), put(0.07, 0.16, 0.10),put(0.07, 0.15, 0.04),put(0.07, 0.12, 0.02) };
			body[24] = new polygon3D(v, put(0.07, 0.12, 0.13),put(0.07, 0.12, 0.02),  put(0.07, 0.02, 0.13), mainThread.textures[skinTextureIndex], 1, 1,1);
			
			v = new vector[]{put(0.07, 0.16, 0.10), put(0, 0.16, 0.10), put(0, 0.15, 0.10), put(0.07, 0.15, 0.10)};
			body[25] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.1f,1);
			
			v = new vector[]{put(0.07, 0.12, 0.02), put(0.07, 0.12, 0.07), put(0.07, 0.04, 0.07), put(0.07, 0.04, 0.02) };
			body[26] = new polygon3D(v, put(0.07, 0.12, 0.02), put(0.07, 0.12, 0.13), put(0.07, 0.02, 0.02), mainThread.textures[skinTextureIndex], 1, 1,1);
			
			v = new vector[]{put(0.07, 0.04, 0.02), put(0.07, 0.04, 0.07), put(0.07, 0.12, 0.07) , put(0.07, 0.12, 0.02)};
			body[27] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.1f,1);
			
			v = new vector[]{put(0.07, 0.12, 0.07), put(0.06, 0.12, 0.07), put(0.06, 0.04, 0.07), put(0.07, 0.04, 0.07)};
			body[28] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.1f,0.5f,1);
			
			v = new vector[]{put(0.01, 0.12, 0.07), put(0, 0.12, 0.07), put(0, 0.04, 0.07), put(0.01, 0.04, 0.07)};
			body[29] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.1f,0.5f,1);
			
			v = new vector[]{put(0.07, 0.08, 0.07), put(0, 0.08, 0.07), put(0, 0.04, 0.11), put(0.07, 0.04, 0.11)};
			body[30] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.5f,0.5f,1);
			
			v = new vector[]{put(0.07, 0.08, 0.07), put(0.07, 0.04, 0.11), put(0.07, 0.04, 0.07)};
			body[31] = new polygon3D(v, put(0.07, 0.12, 0.02), put(0.07, 0.12, 0.13), put(0.07, 0.02, 0.02), mainThread.textures[skinTextureIndex], 1, 1,1);
			
			
			v = new vector[]{put(0.055, 0.21, 0), put(0.055, 0.21, 0.06), put(0.055, 0.18, 0.06),put(0.055, 0.18, 0)};
			body[32] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[25], 4f,4f,1);
			
			v = new vector[]{put(0.015, 0.18, 0), put(0.015, 0.18, 0.06), put(0.015, 0.21, 0.06),put(0.015, 0.21, 0)};
			body[33] = new polygon3D(v, v[2].myClone(), v[3].myClone(), v[1].myClone(), mainThread.textures[25], 4f,4f,1);
			
			v = new vector[]{put(0.055, 0.21, 0), put(0.015, 0.21, 0), put(0.015, 0.21, 0.06), put(0.055, 0.21, 0.06)};
			body[34] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[25], 4f,4f,1);
			body[34].shadowBias = 30000;
			
			v = new vector[]{put(0.055, 0.21, 0.06), put(0.055, 0.21, 0.12), put(0.055, 0.18, 0.12),put(0.055, 0.18, 0)};
			body[35] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[25], 4f,4f,1);
			
			v = new vector[]{put(0.015, 0.18, 0.06), put(0.015, 0.18, 0.12), put(0.015, 0.21, 0.12),put(0.015, 0.21, 0)};
			body[36] = new polygon3D(v, v[2].myClone(), v[3].myClone(), v[1].myClone(), mainThread.textures[25], 4f,4f,1);
			
			v = new vector[]{put(0.055, 0.21, 0.06), put(0.015, 0.21, 0.06), put(0.015, 0.21, 0.12), put(0.055, 0.21, 0.12)};
			body[37] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[25], 4f,4f,1);
			body[37].shadowBias = 50000;
			
			
			double theta = Math.PI/12;
			double r = 0.015;
			
			start.add(0,(float)(0.18 + r),0.12f);
			for(int i = 0; i < 12; i++){
				v = new vector[]{put(0.055, r*Math.cos((i+1)*theta), r*Math.sin((i+1)*theta)),
								 put(0.055, r*Math.cos(i*theta), r*Math.sin(i*theta)),
								 put(0.015, r*Math.cos(i*theta), r*Math.sin(i*theta)),
								 put(0.015, r*Math.cos((i+1)*theta),  r*Math.sin((i+1)*theta))
								
								};
				body[38 + i] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[25], 4f,4f,1);
				
			}
			
			
			v = new vector[13];
			for(int i = 0; i < 13; i ++){
				v[i] = put(0.055, r*Math.cos(i*theta), r*Math.sin(i*theta));
			}
			body[50] = new polygon3D(v, put(0.055, 0.21, 0.06), put(0.055, 0.21, 0.12), put(0.055, 0.18, 0), mainThread.textures[25], 4f,4f,1);
			
			vector[] v2 = new vector[13];
			for(int i = 0; i < 13; i ++){
				v2[i] = v[12 -i].myClone();
				v2[i].x = 0.015f;
			}
			body[51] = new polygon3D(v2, put(0.015, 0.21, 0.12), put(0.015, 0.21, 0), put(0.015, 0.18, 0.12), mainThread.textures[25], 4f,4f,1);
			
			start.add(0,(float)(-0.18 - r),-0.12f);
			
			drill0 = new polygon3D[32];
			
			makeTriangle(drill0, 0, 0, 0,0,0.01f);
			makeTriangle(drill0, 4, 0, 0,0,0.03f);
			makeTriangle(drill0, 8, 0, 0,0,0.05f);
			makeTriangle(drill0, 12, 0, 0,0,0.07f);
			makeTriangle(drill0, 16, 0, 0,0,0.09f);
			makeTriangle(drill0, 20, 0, 0,0,0.11f);
			makeTriangle(drill0, 24, 55, 0,0.085f,-0.045f);
			makeTriangle(drill0, 28, 100, 0, 0.23f,-0.075f);
			
			
			drill1 = new polygon3D[32];
			
			makeTriangle(drill1, 0, 0, 0,0,0.0166f);
			makeTriangle(drill1, 4, 0, 0,0,0.0366f);
			makeTriangle(drill1, 8, 0, 0,0,0.0566f);
			makeTriangle(drill1, 12, 0, 0,0,0.0766f);
			makeTriangle(drill1, 16, 0, 0,0,0.0966f);
			makeTriangle(drill1, 20, 15, 0,0.0065f,0.062f);
			makeTriangle(drill1, 24, 70, 0,0.13f,-0.068f);
			makeTriangle(drill1, 28, 0, 0,0, -0.0034f);
			
			
			drill2 = new polygon3D[32];
			
			makeTriangle(drill2, 0, 0, 0,0,0.0166f + 0.0066f);
			makeTriangle(drill2, 4, 0, 0,0,0.0366f + 0.0066f);
			makeTriangle(drill2, 8, 0, 0,0,0.0566f + 0.0066f);
			makeTriangle(drill2, 12, 0, 0,0,0.0766f + 0.0066f);
			makeTriangle(drill2, 16, 0, 0,0,0.0966f + 0.0066f);
			makeTriangle(drill2, 20, 40, 0,0.05f,-0.012f);
			makeTriangle(drill2, 24, 80, 0,0.16f,-0.075f);
			makeTriangle(drill2, 28, 0, 0,0, -0.0034f + 0.0066f);
			
							
			
			int YZ_angle = 50;
			tempVector.set(0,-0.01f, -0.08f);
			for(int i = 32; i < body.length; i++){
				
				body[i].origin.rotate_YZ(YZ_angle);
				body[i].origin.add(tempVector);
				
				body[i].bottomEnd.rotate_YZ(YZ_angle);
				body[i].bottomEnd.add(tempVector);
				
				body[i].rightEnd.rotate_YZ(YZ_angle);
				body[i].rightEnd.add(tempVector);
			
			
					
				for(int j = 0; j < body[i].vertex3D.length; j++){
					
					body[i].vertex3D[j].rotate_YZ(YZ_angle);
					body[i].vertex3D[j].add(tempVector);
					
					
					
				}
				body[i].normal.rotate_YZ(YZ_angle);
			}
			
			for(int i = 0; i < body.length; i++){
				body[i].findDiffuse();
				body[i].parentObject = this;
				
			}
			
			
			for(int i = 0; i < drill0.length; i++){
				
				drill0[i].origin.rotate_YZ(YZ_angle);
				drill0[i].origin.add(tempVector);
				
				drill0[i].bottomEnd.rotate_YZ(YZ_angle);
				drill0[i].bottomEnd.add(tempVector);
				
				drill0[i].rightEnd.rotate_YZ(YZ_angle);
				drill0[i].rightEnd.add(tempVector);
				
				drill1[i].origin.rotate_YZ(YZ_angle);
				drill1[i].origin.add(tempVector);
				
				drill1[i].bottomEnd.rotate_YZ(YZ_angle);
				drill1[i].bottomEnd.add(tempVector);
				
				drill1[i].rightEnd.rotate_YZ(YZ_angle);
				drill1[i].rightEnd.add(tempVector);
				
				drill2[i].origin.rotate_YZ(YZ_angle);
				drill2[i].origin.add(tempVector);
				
				drill2[i].bottomEnd.rotate_YZ(YZ_angle);
				drill2[i].bottomEnd.add(tempVector);
				
				drill2[i].rightEnd.rotate_YZ(YZ_angle);
				drill2[i].rightEnd.add(tempVector);
			
			
					
				for(int j = 0; j < drill0[i].vertex3D.length; j++){
					
					drill0[i].vertex3D[j].rotate_YZ(YZ_angle);
					drill0[i].vertex3D[j].add(tempVector);
					
					drill1[i].vertex3D[j].rotate_YZ(YZ_angle);
					drill1[i].vertex3D[j].add(tempVector);
					
					drill2[i].vertex3D[j].rotate_YZ(YZ_angle);
					drill2[i].vertex3D[j].add(tempVector);
					
				}
				
				drill0[i].normal.rotate_YZ(YZ_angle);
				drill0[i].findDiffuse();
				drill0[i].parentObject = this;
				
				drill1[i].normal.rotate_YZ(YZ_angle);
				drill1[i].findDiffuse();
				drill1[i].parentObject = this;
				
				drill2[i].normal.rotate_YZ(YZ_angle);
				drill2[i].findDiffuse();
				drill2[i].parentObject = this;
				
				
			}
			
			start.set(0,0,0);
			cargoCenter = put(0, 0.04, -0.15);
			cargo = new polygon3D[11];
			v =  new vector[]{put(-0.06, 0, -0.02), put(0.06, 0, -0.02), put(0.06, 0, 0.16), put(-0.06, 0, 0.16)};
			cargo[0] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1f,1.5f,1);
			
			v = new vector[]{put(0.07, 0.01, -0.02), put(0.07, 0.01, 0.16), put(0.06, 0, 0.16), put(0.06, 0, -0.02)};
			cargo[1] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1.5f,0.1f,1);
			
			v = new vector[]{put(-0.06, 0, -0.02), put(-0.06, 0, 0.16), put(-0.07, 0.01, 0.16), put(-0.07, 0.01, -0.02)};
			cargo[2] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1.5f,0.1f,1);
			
			v = new vector[]{put(0.07, 0.06, -0.02),put(0.07, 0.06, 0.16), put(0.07, 0.01, 0.16), put(0.07, 0.01, -0.02)};
			cargo[3] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1.5f,0.5f,1);
			
			v = new vector[]{put(-0.07, 0.01, -0.02), put(-0.07, 0.01, 0.16),put(-0.07, 0.06, 0.16), put(-0.07, 0.06, -0.02)};
			cargo[4] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1.5f,0.5f,1);
			
			v = new vector[]{put(-0.07, 0.06, -0.02), put(-0.06, 0.07, -0.02), put(0.06, 0.07, -0.02), put(0.07, 0.06, -0.02), put(0.07, 0.01, -0.02), put(0.06, 0, -0.02), put(-0.06, 0, -0.02), put(-0.07, 0.01, -0.02)};
			cargo[5] = new polygon3D(v, put(-0.07, 0.07, -0.02), put(0.07, 0.07, -0.02),put(-0.07, 0.01, -0.02), mainThread.textures[skinTextureIndex], 1f,0.5f,1);
			
			v = new vector[]{put(-0.07, 0.01, 0.16), put(-0.06, 0, 0.16), put(0.06, 0, 0.16), put(0.07, 0.01, 0.16), put(0.07, 0.06, 0.16), put(0.06, 0.07, 0.16),  put(-0.06, 0.07, 0.16), put(-0.07, 0.06, 0.16)};
			cargo[6] = new polygon3D(v, put(0.07, 0.07, 0.16), put(-0.07, 0.07, 0.16), put(0.07, 0.01, 0.16), mainThread.textures[skinTextureIndex], 1f,0.5f,1);
			
			v = new vector[]{put(-0.06, 0.07, 0.16), put(0.06, 0.07, 0.16), put(0.06, 0.07, -0.02), put(-0.06, 0.07, -0.02)};
			cargo[7] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 0.8f,1.3f,1);
			
			v = new vector[]{put(0.065, 0.06, 0.161), put(0.005, 0.06, 0.161), put(0.005, 0.02, 0.161), put(0.065, 0.02, 0.161)};
			cargo[8] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[27], 1f,1f,1);
			
			v = new vector[]{put(0.06, 0.07, -0.02), put(0.06, 0.07, 0.16), put(0.07, 0.06, 0.16),  put(0.07, 0.06, -0.02)};
			cargo[9] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1.5f,0.1f,1);
			
			v = new vector[]{put(-0.07, 0.06, -0.02), put(-0.07, 0.06, 0.16), put(-0.06, 0.07, 0.16),  put(-0.06, 0.07, -0.02)};
			cargo[10] = new polygon3D(v, v[0], v[1], v[3], mainThread.textures[skinTextureIndex], 1.5f,0.1f,1);
			
			
			start.set(0,0,0);
			pillarCenter = put(0, 0.035,0);
			pillars = new polygon3D[98];
			
			theta = Math.PI/12;
			r = 0.008;
			
			for(int i = 0; i < 24; i++){
				v = new vector[]{put(r*Math.cos((i+1)*theta) - 0.03,  r*Math.sin((i+1)*theta), 0),
								put(r*Math.cos(i*theta) - 0.03, r*Math.sin(i*theta), 0),
								put(r*Math.cos(i*theta) - 0.03, r*Math.sin(i*theta), -0.07 ),
						 		put(r*Math.cos((i+1)*theta) - 0.03, r*Math.sin((i+1)*theta), -0.07),
								
								};
				pillars[i] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[28], 4f,4f,1);
			}
			
			v = new vector[24];
			for(int i = 0; i < 24; i ++){
				v[23 -i] = put(r*Math.cos(i*theta) - 0.03, r*Math.sin(i*theta), -0.07);
			}
			pillars[24] = new polygon3D(v, put(0.21 - 0.03, 0.06, -0.07), put(0.21 - 0.03, 0.12, -0.07), put(0.18 - 0.03, 0, -0.07), mainThread.textures[28], 4f,4f,1);
			
			for(int i = 0; i < 24; i++){
				v = new vector[]{put(r*Math.cos((i+1)*theta) + 0.03,  r*Math.sin((i+1)*theta), 0),
								put(r*Math.cos(i*theta) + 0.03, r*Math.sin(i*theta), 0),
								put(r*Math.cos(i*theta) + 0.03, r*Math.sin(i*theta), -0.07 ),
						 		put(r*Math.cos((i+1)*theta) + 0.03, r*Math.sin((i+1)*theta), -0.07),
								
								};
				pillars[25 + i] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[28], 4f,4f,1);
			}
			
			v = new vector[24];
			for(int i = 0; i < 24; i ++){
				v[23 -i] = put(r*Math.cos(i*theta) + 0.03, r*Math.sin(i*theta), -0.07);
			}
			pillars[49] = new polygon3D(v, put(0.21 + 0.03, 0.06, -0.07), put(0.21 + 0.03, 0.12, -0.07), put(0.18 + 0.03, 0, -0.07), mainThread.textures[28], 4f,4f,1);
			
			r = 0.004;
			for(int i = 0; i < 24; i++){
				v = new vector[]{put(r*Math.cos((i+1)*theta) - 0.03,  r*Math.sin((i+1)*theta), -0.07),
								put(r*Math.cos(i*theta) - 0.03, r*Math.sin(i*theta), -0.07),
								put(r*Math.cos(i*theta) - 0.03, r*Math.sin(i*theta), -0.15 ),
						 		put(r*Math.cos((i+1)*theta) - 0.03, r*Math.sin((i+1)*theta), -0.15),
								
								};
				pillars[50 + i ] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[29], 4f,4f,1);
			}
			
			for(int i = 0; i < 24; i++){
				v = new vector[]{put(r*Math.cos((i+1)*theta) + 0.03,  r*Math.sin((i+1)*theta), -0.07),
								put(r*Math.cos(i*theta) + 0.03, r*Math.sin(i*theta), -0.07),
								put(r*Math.cos(i*theta) + 0.03, r*Math.sin(i*theta), -0.15 ),
						 		put(r*Math.cos((i+1)*theta) + 0.03, r*Math.sin((i+1)*theta), -0.15),
								
								};
				pillars[74 + i ] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[29], 4f,4f,1);
			}
			
		}
		
		bodyClone = clonePolygons(body,true);
		drillClone0 = clonePolygons(drill0,true); 
		drillClone1 = clonePolygons(drill1,true); 
		drillClone2 = clonePolygons(drill2,true); 
		cargoClone = clonePolygons(cargo,true);
		cargoCenterClone = new vector(0,0,0);
		pillarsClone = clonePolygons(pillars,true);
		pillarCenterClone = new vector(0,0,0);
		
		if(teamNo != 0){
			for(int i = 0; i < body.length; i++){
				if(body[i].myTexture.ID == 23)
					bodyClone[i].myTexture = mainThread.textures[10];
			}
			
			for(int i = 0; i < cargo.length; i++){
				if(cargo[i].myTexture.ID == 23)
					cargoClone[i].myTexture = mainThread.textures[10];
			}
		}
	}
	
	public void makeTriangle(polygon3D[] triangles, int startIndex, int angle, float x, float y, float z){
		float x_old = start.x;
		float y_old = start.y;
		float z_old = start.z;
		start.set(x,y,z);
		jDirection.rotate_YZ(angle);
		kDirection.rotate_YZ(angle);
		
		v = new vector[]{put(0.02, 0.225, 0), put(0.05, 0.225, 0), put(0.05, 0.21, 0), put(0.02, 0.21, 0)};
		triangles[startIndex] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[26], 4f,4f,1);
		
		v = new vector[]{put(0.05, 0.225, 0), put(0.02, 0.225, 0), put(0.02, 0.21, 0.01f), put(0.05, 0.21, 0.01f)};
		triangles[startIndex + 1] = new polygon3D(v, v[0].myClone(), v[1].myClone(), v[3].myClone(), mainThread.textures[26], 4f,4f,1);
		
		v = new vector[]{put(0.05, 0.225, 0),  put(0.05, 0.21, 0.01f), put(0.05, 0.21, 0)};
		triangles[startIndex + 2] = new polygon3D(v, v[0].myClone(), put(0.05, 0.225, 0.01), v[2].myClone(), mainThread.textures[26], 4f,4f,1);
		
		v = new vector[]{put(0.02, 0.21, 0),  put(0.02, 0.21, 0.01f), put(0.02, 0.225, 0)};
		triangles[startIndex + 3] = new polygon3D(v, put(0.02, 0.21, 0f), put(0.02, 0.21, 0.01), put(0.02, 0.225, 0f), mainThread.textures[26], 4f,4f,1);
		
		
		start.set(x_old, y_old, z_old);
		jDirection.rotate_YZ(360 - angle);
		kDirection.rotate_YZ(360 -angle);
		
	}
	
	
	
	//update the model 
	public void update(){		
		
	
		//handle unloading gold ore event
		if(unloadingCount > 0){
			if(unloadingCount > 69 && cargoAngle > 300)
				cargoAngle-=2;
				
			
			if(unloadingCount < 31 && cargoAngle < 360)
				cargoAngle+=2;
			
			unloadingCount--;
		}
		
		//handle drilling event
		if(drillingCount > 0){
			drillIndex--;
			drillIndex = (drillIndex + 3)%3;
			drillingCount --;
		}
		
		if(waitingCount > 0)
			waitingCount --;
		
		if(underAttackCountDown > 0)
			underAttackCountDown--;
		
		
		//check if harvester has been destroyed
		if(currentHP <= 0){
			//spawn an explosion when the tank is destroyed
			float[] tempFloat = theAssetManager.explosionInfo[theAssetManager.explosionCount];	
			tempFloat[0] = centre.x;
			tempFloat[1] = centre.y - 0.05f;
			tempFloat[2] = centre.z;
			tempFloat[3] = 2.5f;
			tempFloat[4] = 1;
			tempFloat[5] = 0;
			tempFloat[6] = 7;
			tempFloat[7] = this.height;
			theAssetManager.explosionCount++; 
			theAssetManager.removeObject(this); 
			removeFromGridMap(); 
			if(attacker.teamNo != teamNo)
				attacker.experience+=25;
			if(insideRefinery){
				if(myRefinery!= null)
					myRefinery.isBusy = false;
			}
				
			return;
		}
		
		//carry out commands given by the player or AI
		if(!disableUnitLevelAI)
			carryOutCommands();
		
		
		
		if(tightSpaceManeuverCountDown > 0)
			tightSpaceManeuverCountDown--;
		
		if(heuristicRecalculationCountDown > 0)
			heuristicRecalculationCountDown--;

		//update centre
		if(Math.abs(movement.x) + Math.abs(movement.z) < 0.25f){
			centre.add(movement);
			boundary2D.setOrigin((int)(centre.x*64) - 8, (int)(centre.z*64) + 8);
			updateOccupiedTiles(boundary2D.x1, boundary2D.y1);
		}else{
			movement.reset();
		}
		
		
		//update center in camera coordinate
		tempCentre.set(centre);
		tempCentre.y -= 0.2f;
		tempCentre.subtract(camera.position);
		tempCentre.rotate_XZ(camera.XZ_angle);
		tempCentre.rotate_YZ(camera.YZ_angle); 
		tempCentre.updateLocation();
		
		visionBoundary.x = (int) (tempCentre.screenX - visionW);
		visionBoundary.y = (int) (tempCentre.screenY - visionH);
		visionInsideScreen = camera.screen.intersects(visionBoundary);
		
		
		//create vision for enemy commander
		if(teamNo == 1){
			xPos = boundary2D.x1/16 - 6 + 10;
			yPos = 127 - boundary2D.y1/16 - 6 + 10;
			
			for(int y = 0; y < 13; y++){
				for(int x = 0; x < 13; x++){
					if(bitmapVisionForEnemy[x+ y*13])
						enemyCommander.tempBitmap[xPos + x + (yPos+y)*148] =true;
				}
			}
		}
		
		if(visionInsideScreen && teamNo == 0){
			
			tempFloat = theAssetManager.visionPolygonInfo[theAssetManager.visionPolygonCount];
			tempFloat[0] = teamNo;
			tempFloat[1] = centre.x;
			tempFloat[2] = -0.4f;
			tempFloat[3] = centre.z;
			tempFloat[4] = 0;
			theAssetManager.visionPolygonCount++;
		}
		
		//check if the tank object is visible in mini map
		visible_minimap = theAssetManager.minimapBitmap[boundary2D.x1/16 + (127 - boundary2D.y1/16)*128];

		if(teamNo == 0 || visible_minimap){
			tempInt = theAssetManager.unitsForMiniMap[theAssetManager.unitsForMiniMapCount];
			tempInt[0] = teamNo;
			tempInt[1] = boundary2D.x1/16;
			tempInt[2] = 127 - boundary2D.y1/16;
			tempInt[3] = 0;
			if(teamNo == 0 && underAttackCountDown > 0)
				tempInt[4] = 10001;
			else
				tempInt[4] = 0;
			theAssetManager.unitsForMiniMapCount++;
		}
		
		
		
		//test if the tank object is visible in camera point of view
		if(visible_minimap){
			if(currentHP <= 130 && (mainThread.gameFrame + ID) % 3 ==0){
				//spawn smoke particle if the tank is badly damaged
				float[] tempFloat = theAssetManager.smokeEmmiterList[theAssetManager.smokeEmmiterCount];
				tempFloat[0] = centre.x + (float)(Math.random()/20) - 0.025f;
				tempFloat[1] = centre.y - 0.06f;
				tempFloat[2] = centre.z + (float)(Math.random()/20) - 0.025f;
				tempFloat[3] = 0.7f;
				tempFloat[4] = 1;
				tempFloat[5] = 11;
				tempFloat[6] = this.height;
				
				theAssetManager.smokeEmmiterCount++;
			}
			
			
			
			if(visibleBoundary.contains(tempCentre.screenX, tempCentre.screenY)){
				visible = true;
				if(screenBoundary.contains(tempCentre.screenX, tempCentre.screenY))
					withinViewScreen = true;
				else
					withinViewScreen = false;
			}else{
				visible = false;
				
			}
		}else{
			mainThread.pc.deSelect(this);
			visible = false;
		}
		
		
		if(visible){
			updateGeometry();
				
			
			for(int i = 0; i < bodyClone.length; i++){
				bodyClone[i].update_lightspace();	
			}
			
			polygon3D[] drillClone;
			drillClone = null;		
			if(drillIndex == 0){
				drillClone = drillClone0;
			}
			if(drillIndex == 1){
				drillClone = drillClone1;
			}
			if(drillIndex == 2){
				drillClone = drillClone2;
			}
			
			for(int i = 0; i < drillClone.length; i++){
				drillClone[i].update_lightspace();	
			}
			
			for(int i = 0; i < cargoClone.length; i++){
				cargoClone[i].update_lightspace();	
			}
			
			if(unloadingCount > 0){
				for(int i = 0; i < pillarsClone.length; i++){
					pillarsClone[i].update_lightspace();	
				}
			}
			
			theAssetManager.visibleUnit[theAssetManager.visibleUnitCount] = this;
			theAssetManager.visibleUnitCount++;
			
			if(waitingCount > 0)
				movement.reset();
		}
		
	}
	
	//carry out commands given by player or  AI commander
	public void carryOutCommands(){
		
		
		if(currentCommand == StandBy){
			resetLogicStatus();
			jobStatus = idle;
			
		}else if(currentCommand == move){
			float d = Math.abs(destinationX - centre.x) + Math.abs(destinationY - centre.z);
			
			if(waitingCount <= 1){
				if(d < 1.5f){
					if(jobStatus == headingToMine){
						//check if the mining spot is already occupied
						tile = mainThread.gridMap.tiles[myMiningPosition];
						for(int i = 0; i < 5; i++){
							if(tile[i] != null && tile[i] != this){
								if(tile[i].getMovement().x ==0 && tile[i].getMovement().z == 0){
									boolean foundFreeSpot = false;
									for(int j = 0; j < 7; j++){
										int p = miningPositions[(myMiningPosition + j)%8];
										tile = mainThread.gridMap.tiles[p];
										boolean freespot = true;
										
										for(int k = 0; k < 5; k++){
											if(tile[k] != null){
												freespot = false;
												break;
											}
										}
										
										if(freespot){
											myMiningPosition = p;
											int xPosition = myMiningPosition%128;
											int yPosition = 127 - myMiningPosition/128;
											this.destinationX = xPosition*0.25f +0.125f;
											this.destinationY = yPosition*0.25f +0.125f;
											foundFreeSpot = true;
											break;
										}
									}
									
									if(!foundFreeSpot)
										waitingCount = 15;
									
									break;
								}else{
									waitingCount = 15;
								}
							}
						}
						
					}
				}
				
				if(d < 2){
					if(jobStatus == returningToRefinery){
						if(myRefinery == null || myRefinery.currentHP <=0 || myRefinery.isBusy || myRefinery.droppingAreaIsFull(this)){
							returnToRefinery(null);
							movement.reset();
						}
					}
				}
			}
			
			
			 
			if(waitingCount == 0){
				if(jobStatus == leavingRefinery){
					if(centre.z != insideRefineryPositionY - 0.25f){
						if(centre.z - (insideRefineryPositionY - 0.25f)  < speed) 
							movement.set(0,0, (insideRefineryPositionY - 0.25f) - centre.z);
						else
							movement.set(0,0,-speed);
						
						xPos_old = boundary2D.x1;
						yPos_old = boundary2D.y1;
						xPos = (int)((centre.x + movement.x)*64) - 8;
						yPos = (int)((centre.z + movement.z)*64) + 8;
						boundary2D.setOrigin(xPos, yPos);
						
						boolean canMove = true;
						for(int i = 0; i < 4; i++){
							solidObject o = mainThread.gridMap.tiles[myRefinery.tileIndex[5]+128][i];
							if(o != null && o != this){
								if(o.boundary2D.intersect(boundary2D)){
									canMove = false;
									if(o.teamNo != teamNo)           //deactivate  enemy unit's cloak ability on collision
										o.cloakCooldownCount = 60;
									break;
								}
							}
						}
						
						if(!canMove){
							movement.reset();
						}
						
						boundary2D.x1 = xPos_old;
						boundary2D.y1 = yPos_old;
						
					}else{
						jobStatus = headingToMine;
						myRefinery.isBusy = false;
						insideRefinery = false;
						harvest(myGoldMine);
					}
					if(myRefinery.currentHP <= 0)
						harvest(myGoldMine);
				}else if(jobStatus == facingDownward){
					if(bodyAngle != 180){
						int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, 180, bodyTurnRate) + 360)%360;
						bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
					}else{
						if(myRefinery.hasExit()) 
							jobStatus = leavingRefinery;
						else
							waitingCount = 15;
					}
					movement.reset();
					if(myRefinery.currentHP <= 0)
						returnToRefinery(null);
				}else if(jobStatus == unloadingCargo){
					if(unloadingCount == 0)
						unloadingCount = 100;
					if(unloadingCount == 50){
						if(teamNo == 0)
							mainThread.pc.theBaseInfo.currentCredit +=cargoDeposite;
						else
							mainThread.ec.theBaseInfo.currentCredit +=cargoDeposite;
						cargoDeposite = 0;
						progressStatus = 100*cargoDeposite/700;
					}
					if(unloadingCount == 1){
						jobStatus = facingDownward;
					}
					movement.reset();
					if(myRefinery.currentHP <= 0)
						returnToRefinery(null);
				}else if(jobStatus == facingRight){
					if(bodyAngle != 90){
						int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, 90, bodyTurnRate) + 360)%360;
						bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
					}else{
					
						jobStatus = unloadingCargo;
					
					}
					movement.reset();
					if(myRefinery.currentHP <= 0)
						returnToRefinery(null);
				}else if(jobStatus == enteringRefinery){
					if(centre.z != insideRefineryPositionY){
						if(insideRefineryPositionY - centre.z < speed)
							movement.set(0,0,insideRefineryPositionY - centre.z);
						else
							movement.set(0,0,speed);
					}else{
						jobStatus = facingRight;
						movement.reset();
					}
					if(myRefinery.currentHP <= 0)
						returnToRefinery(null);
				}else if(jobStatus == facingGoldMine){
					destinationAngle = geometry.findAngle(centre.x, centre.z, myGoldMine.centre.x, myGoldMine.centre.z);
					immediateDestinationAngle = destinationAngle;	
					if(bodyAngle != immediateDestinationAngle){
						int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, immediateDestinationAngle, bodyTurnRate) + 360)%360;
						bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
					}else{
						jobStatus = isDrilling;
						drillingCount = 700;
					}
					movement.reset();
				}else if(jobStatus == facingRefinery){
					
					if((bodyAngle%360) != 0){
						int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, 0, bodyTurnRate) + 360)%360;
						bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
					}else{
						jobStatus = enteringRefinery;
						myRefinery.isBusy = true;
						insideRefinery = true;
						myRefinery.unloadOreCountDown = 200;
					}
					movement.reset();
					if(myRefinery.currentHP <= 0)
						returnToRefinery(null);
					
				}else if(jobStatus == isDrilling){
					if(myGoldMine.goldDeposite > 1){
						myGoldMine.goldDeposite-=1;
						cargoDeposite+=1;
						progressStatus = 100*cargoDeposite/700;
					}else if(cargoDeposite >0)
						returnToRefinery(null);
					
					if(drillingCount == 0 || cargoDeposite == 700 || myGoldMine.goldDeposite == 0){	
						returnToRefinery(null);
					}
					movement.reset();
				}else{
					//check if the harvest is at a position that is suitable for mining 
					if(jobStatus == headingToMine ) {
						int nodeX = (int)(centre.x * 64)/16;
						int nodeY = 127 - (int)(centre.z * 64)/16;
						int modX = (int)(centre.x * 64) % 16;
						int modY = (int)(centre.z * 64) % 16;
						
						if(modX == 8 && modY == 8 && d < 1) {
							for(int i =0; i < 8; i++) {
								int miningNodeX = miningPositions[i] % 128;
								int miningNodeY = miningPositions[i] / 128;
								
								if(miningNodeX == nodeX && miningNodeY == nodeY) {
									int xPosition = miningPositions[i]%128;
									int yPosition = 127 - miningPositions[i]/128;
									destinationX = xPosition*0.25f +0.125f;
									destinationY = yPosition*0.25f +0.125f;
									break;
								}
							 
							}
						}
					} 
					
					performPathFindingLogic();
				}
			}else{
				movement.reset();
			}
			
		}
	}
	
	//use a path finder to move to desination
	public void performPathFindingLogic(){
		
		
		if(!pathIsFound  && heuristicRecalculationCountDown == 0){
			
			
			
			int destX  = (int)(destinationX * 64)/16;
			int destY =  127 - (int)(destinationY * 64)/16;
			
			pathIsFound = PathFinder.createHeuristicMap(heuristicMap,occupiedTile0, occupiedTile1, occupiedTile2, occupiedTile3, destX, destY);
			heuristicRecalculationCountDown = 32;
			
			
			
			if(pathIsFound){
					
				//find the first node in the path
				int  nextTile0 = findAdjacentTileWithSmallestHeuristic(occupiedTile0);
				int  nextTile1 = findAdjacentTileWithSmallestHeuristic(occupiedTile1);
				int  nextTile2 = findAdjacentTileWithSmallestHeuristic(occupiedTile2);
				int  nextTile3 = findAdjacentTileWithSmallestHeuristic(occupiedTile3);
				
				if(occupiedTile1 == -1)
					nextTile1 = occupiedTile1;
				if(occupiedTile2 == -1)
					nextTile2 = occupiedTile2;
				if(occupiedTile3 == -1)
					nextTile3 = occupiedTile3;
				
				if(nextTile0 != occupiedTile0){
					nextNodeX = 0.125f + (nextTile0%128) * 0.25f;
					nextNodeY = 0.125f +  (127 - (nextTile0/128)) * 0.25f;
				
					
				}else if(nextTile1 != occupiedTile1){
					nextNodeX = 0.125f + (nextTile1%128) * 0.25f;
					nextNodeY = 0.125f +  (127 - (nextTile1/128)) * 0.25f;
				
				}else if(nextTile2 != occupiedTile2){
					nextNodeX = 0.125f + (nextTile2%128) * 0.25f;
					nextNodeY = 0.125f +  (127 - (nextTile2/128)) * 0.25f;
					
				}else if(nextTile3 != occupiedTile3){
					nextNodeX = 0.125f + (nextTile3%128) * 0.25f;
					nextNodeY = 0.125f +  (127 - (nextTile3/128)) * 0.25f;
					
				}
			}
		}
		
		if(pathIsFound){
			
			
			
			movement.reset();
		
			//check if the harvester has reached next node in the path
			if(centre.x == nextNodeX && centre.z == nextNodeY){
				//check if the harvester has reached the destination
				int destX  = (int)(destinationX * 64)/16;
				int destY =  127 - (int)(destinationY * 64)/16;
				int nodeX = (int)(centre.x * 64)/16;
				int nodeY = 127 - (int)(centre.z * 64)/16;
				if(destX == nodeX && destY == nodeY){
					
					
					pathIsFound = false;
					resetLogicStatus();
					
					if(jobStatus == idle)
						currentCommand = StandBy;
					else{
						if(jobStatus == headingToMine){
							jobStatus = facingGoldMine;
							if(myGoldMine.goldDeposite ==0){
								currentCommand = StandBy;
							}
						}
						
						if(jobStatus == returningToRefinery){
							jobStatus = facingRefinery;
							if(myRefinery.currentHP == 0){
								returnToRefinery(null);
							}
						}
						
					}
						
					return;
				}else{
					//if destination hasn't reached, find the next node
					int nextTile0 = findAdjacentTileWithSmallestHeuristic(occupiedTile0);
					nextNodeX = 0.125f + (nextTile0%128) * 0.25f;
					nextNodeY = 0.125f +  (127 - (nextTile0/128)) * 0.25f;
					
				}
			}
			
			
			
			float distanceToNextNode = (float)Math.sqrt((nextNodeX - centre.x) * (nextNodeX - centre.x) + (nextNodeY - centre.z) * (nextNodeY - centre.z));
			calculateMovement();
			destinationAngle = geometry.findAngle(centre.x, centre.z, nextNodeX, nextNodeY);
			immediateDestinationAngle = destinationAngle;	
			
			if(Math.abs(bodyAngle - immediateDestinationAngle) > 45 && Math.abs(bodyAngle - immediateDestinationAngle) < 315){
				
				int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, immediateDestinationAngle, bodyTurnRate) + 360)%360;
				bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
				movement.reset();
				
			}else{
				if(bodyAngle != immediateDestinationAngle){
					int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, immediateDestinationAngle, bodyTurnRate) + 360)%360;
					bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
				}
				
				movement.set(nextNodeX - centre.x, 0, nextNodeY - centre.z);
				
				if(speed < distanceToNextNode){
					movement.unit();
					movement.scale(speed);
				}
				
				//check collision
				xPos_old = boundary2D.x1;
				yPos_old = boundary2D.y1;
				xPos = (int)((centre.x + movement.x)*64) - 8;
				yPos = (int)((centre.z + movement.z)*64) + 8;
				boundary2D.setOrigin(xPos, yPos);
				
				Rect r = checkForCollision(boundary2D);
				boundary2D.setOrigin(xPos_old, yPos_old);
				
				if(r != null){
					movement.reset();
					pathIsFound = false;
					if(r.owner.teamNo != teamNo)           //deactivate  enemy unit's cloak ability on collision
						r.owner.cloakCooldownCount = 60;
				}
				
				
			}
			
			return;
		}
			
		
		if(!pathIsFound){
			if((movement.x == 0 && movement.z == 0) || mainThread.gridMap.tiles[occupiedTile0][4] != null){
				if((Math.abs(destinationX - centre.x) + Math.abs(destinationY - centre.z) > 0.5) ||(jobStatus == idle)){
					heuristicRecalculationCountDown = 64;
				}
			}
			performMovementLogic();
			avoidGettingStucked();
			
			//harvester is always on the move
			if(jobStatus != idle){
				currentCommand = move;
			}
		}
		
	}
	
	public int findAdjacentTileWithSmallestHeuristic(int currentTile){
		int smallestHeurstic = 127;
		int nextTile = currentTile;
		
		boolean[] obstacleMap = mainThread.gridMap.previousObstacleMap;
		
		//check north west tile
		int northWestTile = currentTile - 128 - 1;
		int northTile = currentTile - 128;
		int northEastTile = currentTile - 128 + 1;
		int eastTile = currentTile + 1;
		int southEastTile = currentTile + 1 + 128;
		int southTile = currentTile + 128;
		int southWestTile = currentTile + 128 - 1;
		int westTile = currentTile - 1;
		
		if(northWestTile > 0 && northWestTile < 16384 && obstacleMap[northTile] && obstacleMap[westTile]){
			if(heuristicMap[northWestTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[northWestTile];
				nextTile = northWestTile;
			}
		}
		
		//check north tile
		
		if(northTile > 0 && northTile < 16384){
			if(heuristicMap[northTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[northTile];
				nextTile = northTile;
			}
		}
		
		//check north east tile
		if(northEastTile > 0 && northEastTile < 16384 && obstacleMap[northTile] && obstacleMap[eastTile]){
			if(heuristicMap[northEastTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[northEastTile];
				nextTile = northEastTile;
			}
		}
		
		//check east tile
		
		if(eastTile > 0 && eastTile < 16384){
			if(heuristicMap[eastTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[eastTile];
				nextTile = eastTile;
			}
		}
		
		//check south east tile
		
		if(southEastTile > 0 && southEastTile < 16384 && obstacleMap[southTile] && obstacleMap[eastTile]){
			if(heuristicMap[southEastTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[southEastTile];
				nextTile = southEastTile;
			}
		}
		
		//check south tile
		
		if(southTile > 0 && southTile < 16384){
			if(heuristicMap[southTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[southTile];
				nextTile = southTile;
			}
		}
		
		//check south west tile
		
		if(southWestTile > 0 && southWestTile < 16384 && obstacleMap[southTile] && obstacleMap[westTile]){
			if(heuristicMap[southWestTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[southWestTile];
				nextTile = southWestTile;
			}
		}
		
		//check west tile
		if(westTile > 0 && westTile < 16384){
			if(heuristicMap[westTile] < smallestHeurstic){
				smallestHeurstic = heuristicMap[westTile]; 
				nextTile = westTile;
			}
		}
		
		return nextTile;
	}
	
	//move to a destination position,  ignore any hostile units it encounters 
	public void performMovementLogic(){
		
		//clear things a bit
		unStableObstacle = null;
		
		if(newDestinationisGiven){
			newDestinationisGiven = false;
			
			distanceToDesination = (float)Math.sqrt((destinationX - centre.x) * (destinationX - centre.x) + (destinationY - centre.z) * (destinationY - centre.z));
			calculateMovement();
			destinationAngle = geometry.findAngle(centre.x, centre.z, destinationX, destinationY);
			immediateDestinationAngle = destinationAngle;	
		}
		
		if(Math.abs(bodyAngle - immediateDestinationAngle) > 45 && Math.abs(bodyAngle - immediateDestinationAngle) < 315){
			
			int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, immediateDestinationAngle, bodyTurnRate) + 360)%360;
			bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
			movement.reset();
			
		}else{
			if(bodyAngle != immediateDestinationAngle){
				int bodyAngleDelta = 360 - (geometry.findAngleDelta(bodyAngle, immediateDestinationAngle, bodyTurnRate) + 360)%360;
				bodyAngle= (bodyAngle - bodyAngleDelta + 360)%360;
			}
			
			if(currentMovementStatus == hugRight || currentMovementStatus == hugLeft){
				
				
				if(checkIfDestinationReached() == true){
				
					movement.reset();
					currentCommand = StandBy;
					secondaryCommand = StandBy;
					return;
				}
				hugWalls();  

				return;
			}
			
			
			if(movement.x == 0 && movement.z == 0)
				calculateMovement();
			if(distanceToDesination - speed <= 0){
				movement.scale(speed - distanceToDesination);
				//validate movement
				currentMovementStatus = validateMovement();
				
				
				if(currentMovementStatus == freeToMove){
					resetLogicStatus();
					currentCommand = StandBy;
					secondaryCommand = StandBy;
				}else{

					movement.reset();
					
				}
			}else {
				//validate movement
				currentMovementStatus = validateMovement();
				
				if(currentMovementStatus == freeToMove){
					distanceToDesination -= speed;
				}else{
					movement.reset();
					
				}
			}
		}
	}
		
	public void avoidGettingStucked(){
		//if the object can't move for some period then recalculate the path
		if(movement.x == 0 && movement.z == 0){
			stuckCount++;
		}
		

		if(obstacle != null){
			if((unStableObstacle != null ||  !isStable(obstacle.owner)) && (ID + randomNumber + mainThread.gameFrame)%128 ==0){
				
				newDestinationisGiven = true;
				currentMovementStatus = freeToMove;
				hugWallCoolDown = 0;
				stuckCount = 0;
				randomNumber = gameData.getRandom();
			}
		}
		
		
		
		if(stuckCount > 128){
			newDestinationisGiven = true; 
			stuckCount = 0;
			currentMovementStatus = freeToMove;
			hugWallCoolDown = 0;
			
		}
	}
	
	public void draw(){
		if(!visible)
			return;
		
		for(int i = 0; i < bodyClone.length; i++){
			bodyClone[i].update();
			bodyClone[i].draw();
		}
		
		polygon3D[] drillClone;
		drillClone = null;		
		if(drillIndex == 0){
			drillClone = drillClone0;
		}
		if(drillIndex == 1){
			drillClone = drillClone1;
		}
		if(drillIndex == 2){
			drillClone = drillClone2;
		}
		
		for(int i = 0; i < drillClone.length; i++){
			drillClone[i].update();
			drillClone[i].draw();
		}
		
		for(int i = 0; i < cargoClone.length; i++){
			cargoClone[i].update();
			cargoClone[i].draw();
		}
		
		if(unloadingCount > 0){
			for(int i = 0; i < pillarsClone.length; i++){
				pillarsClone[i].update();
				pillarsClone[i].draw();
			}
		}
		
	}
	
	public vector getMovement(){
		return movement;
	}
	
	
	public void updateGeometry(){
		centre.y-=0.18f;
		
		for(int i = 0; i < bodyClone.length; i++){
			bodyClone[i].origin.set(body[i].origin);
			
			bodyClone[i].origin.rotate_XZ(360 - bodyAngle);
			bodyClone[i].origin.add(centre);
			
				
				
			bodyClone[i].bottomEnd.set(body[i].bottomEnd);
			
			bodyClone[i].bottomEnd.rotate_XZ(360 - bodyAngle);
			bodyClone[i].bottomEnd.add(centre);
		
				
				
			bodyClone[i].rightEnd.set(body[i].rightEnd);
			bodyClone[i].rightEnd.rotate_XZ( 360 - bodyAngle);
			bodyClone[i].rightEnd.add(centre);
		
				
			
			
			for(int j = 0; j < bodyClone[i].vertex3D.length; j++){
				bodyClone[i].vertex3D[j].set(body[i].vertex3D[j]);
				bodyClone[i].vertex3D[j].rotate_XZ(360 -bodyAngle);
				bodyClone[i].vertex3D[j].add(centre);
				
				
				bodyClone[i].normal.set(body[i].normal);
				bodyClone[i].normal.rotate_XZ(360 -bodyAngle);
				bodyClone[i].findDiffuse();
			}
		}
		
		polygon3D[] drill, drillClone;
		drill = null;
		drillClone = null;		
		if(drillIndex == 0){
			drill = drill0;
			drillClone = drillClone0;
		}
		if(drillIndex == 1){
			drill = drill1;
			drillClone = drillClone1;
		}
		if(drillIndex == 2){
			drill = drill2;
			drillClone = drillClone2;
		}
		
		for(int i = 0; i < drillClone.length; i++){
			drillClone[i].origin.set(drill[i].origin);
			drillClone[i].origin.rotate_XZ(360 - bodyAngle);
			drillClone[i].origin.add(centre);
			
				
				
			drillClone[i].bottomEnd.set(drill[i].bottomEnd);
			
			drillClone[i].bottomEnd.rotate_XZ(360 - bodyAngle);
			drillClone[i].bottomEnd.add(centre);
		
				
				
			drillClone[i].rightEnd.set(drill[i].rightEnd);
			drillClone[i].rightEnd.rotate_XZ( 360 - bodyAngle);
			drillClone[i].rightEnd.add(centre);
		
				
			
			
			for(int j = 0; j < drillClone[i].vertex3D.length; j++){
				drillClone[i].vertex3D[j].set(drill[i].vertex3D[j]);
				drillClone[i].vertex3D[j].rotate_XZ(360 -bodyAngle);
				drillClone[i].vertex3D[j].add(centre);
				
				drillClone[i].normal.set(drill[i].normal);
				drillClone[i].normal.rotate_XZ(360 -bodyAngle);
				drillClone[i].findDiffuse();
			}
		}
		
		
		//update cargo center
		cargoCenterClone.set(cargoCenter);
		cargoCenterClone.rotate_XZ(360 -bodyAngle);
		cargoCenterClone.add(centre);
		
		
		for(int i = 0; i < cargoClone.length; i++){
			cargoClone[i].origin.set(cargo[i].origin);
			cargoClone[i].origin.rotate_YZ(cargoAngle);
			cargoClone[i].origin.rotate_XZ(360 - bodyAngle);
			cargoClone[i].origin.add(cargoCenterClone);
			
			cargoClone[i].bottomEnd.set(cargo[i].bottomEnd);
			cargoClone[i].bottomEnd.rotate_YZ(cargoAngle);
			cargoClone[i].bottomEnd.rotate_XZ(360 - bodyAngle);
			cargoClone[i].bottomEnd.add(cargoCenterClone);
		
				
				
			cargoClone[i].rightEnd.set(cargo[i].rightEnd);
			cargoClone[i].rightEnd.rotate_YZ(cargoAngle);
			cargoClone[i].rightEnd.rotate_XZ( 360 - bodyAngle);
			cargoClone[i].rightEnd.add(cargoCenterClone);
		
				
			
			
			for(int j = 0; j < cargoClone[i].vertex3D.length; j++){
				cargoClone[i].vertex3D[j].set(cargo[i].vertex3D[j]);
				cargoClone[i].vertex3D[j].rotate_YZ(cargoAngle);
				cargoClone[i].vertex3D[j].rotate_XZ(360 -bodyAngle);
				cargoClone[i].vertex3D[j].add(cargoCenterClone);
				
				
				cargoClone[i].normal.set(cargo[i].normal);
				cargoClone[i].normal.rotate_YZ(cargoAngle);
				cargoClone[i].normal.rotate_XZ(360 -bodyAngle);
				cargoClone[i].findDiffuse();
			}
		}
		
		if(unloadingCount > 0){
			//update pillars 
			pillarCenterClone.set(pillarCenter);
			pillarCenterClone.rotate_XZ(360 -bodyAngle);
			pillarCenterClone.add(centre);
			pillarAngle = (360- cargoAngle)/5*4;
			
			
			for(int i = 0; i < pillarsClone.length; i++){
				pillarsClone[i].origin.set(pillars[i].origin);
				pillarsClone[i].origin.rotate_YZ(pillarAngle);
				pillarsClone[i].origin.rotate_XZ(360 - bodyAngle);
				pillarsClone[i].origin.add(pillarCenterClone);
				
					
					
				pillarsClone[i].bottomEnd.set(pillars[i].bottomEnd);
				pillarsClone[i].bottomEnd.rotate_YZ(pillarAngle);
				pillarsClone[i].bottomEnd.rotate_XZ(360 - bodyAngle);
				pillarsClone[i].bottomEnd.add(pillarCenterClone);
			
					
					
				pillarsClone[i].rightEnd.set(pillars[i].rightEnd);
				pillarsClone[i].rightEnd.rotate_YZ(pillarAngle);
				pillarsClone[i].rightEnd.rotate_XZ( 360 - bodyAngle);
				pillarsClone[i].rightEnd.add(pillarCenterClone);
			
					
				
				
				for(int j = 0; j < pillarsClone[i].vertex3D.length; j++){
					pillarsClone[i].vertex3D[j].set(pillars[i].vertex3D[j]);
					pillarsClone[i].vertex3D[j].rotate_YZ(pillarAngle);
					pillarsClone[i].vertex3D[j].rotate_XZ(360 -bodyAngle);
					pillarsClone[i].vertex3D[j].add(pillarCenterClone);
					
					
					pillarsClone[i].normal.set(pillars[i].normal);
					pillarsClone[i].normal.rotate_YZ(pillarAngle);
					pillarsClone[i].normal.rotate_XZ(360 -bodyAngle);
					pillarsClone[i].findDiffuse();
				}
			}
		}
		
		centre.y+=0.18f;
	}
	
	public void resetLogicStatus(){
		movement.reset();
		currentMovementStatus = freeToMove;
		stuckCount = 0;
		destinationX = centre.x;
		destinationY = centre.z;
		insideDeistinationRadiusCount = 0;
		obstacle = null;
		drillingCount = 0;
		closeToDestination = false;
		
	}
	
	public void moveTo(float destinationX, float destinationY){		
		if(myRefinery != null){
			if(myRefinery.currentHP >0){
				if(jobStatus >3 )
					return;
			}
		}
		
		
		resetLogicStatus();
		pathIsFound = false;
		this.destinationX = destinationX;
		this.destinationY = destinationY;
		newDestinationisGiven = true;
		heuristicRecalculationCountDown = 0;
		jobStatus = idle;
			
	}
	
	
	public void harvest(solidObject o){      
		
	
		if(drillingCount > 0 && o == myGoldMine)
			return;
		
		if(cargoDeposite == 700){
			return;
		}
		
		if(jobStatus > 3){
			return;
		}
			
		myGoldMine = (goldMine)o;
		
		if(myGoldMine.goldDeposite == 0){
			myGoldMine = null;
			return;
		}
		
		resetLogicStatus();
		pathIsFound = false;
		newDestinationisGiven = true;
		heuristicRecalculationCountDown = 0;
		currentCommand = move;
		jobStatus = headingToMine;
		
		
		//set destination to one of the 8 adjacent tiles around the gold mine
		int goldMineTile = myGoldMine.tileIndex[0];
		miningPositions[0] = goldMineTile - 128;
		miningPositions[1] = goldMineTile - 127;
		miningPositions[2] = goldMineTile + 2;
		miningPositions[3] = goldMineTile + 130;
		miningPositions[4] = goldMineTile + 257;
		miningPositions[5] = goldMineTile + 256;
		miningPositions[6] = goldMineTile + 127;
		miningPositions[7] = goldMineTile -1;
												
		myMiningPosition = miningPositions[(int)((Math.random()*8))];
		int xPosition = myMiningPosition%128;
		int yPosition = 127 - myMiningPosition/128;
		this.destinationX = xPosition*0.25f +0.125f;
		this.destinationY = yPosition*0.25f +0.125f;
	}
	
	
	public void returnToRefinery(solidObject o){
		if(jobStatus == enteringRefinery || jobStatus == leavingRefinery || jobStatus == unloadingCargo || jobStatus == facingRight || jobStatus == facingDownward)
			return;
		
		if(cargoDeposite == 0){
			if(myGoldMine != null){
				harvest(myGoldMine);
			}
			return;
		}
		
		if(o == null){
			//find a nearest refinary
			myRefinery = findNearestRefinery();
			
		}else{
			myRefinery = (refinery)o;
			if(myRefinery.currentHP <=0){
				//find a nearest refinary
				myRefinery = findNearestRefinery();
			}
		}
		
		if(myRefinery != null){
			resetLogicStatus();
			pathIsFound = false;
			newDestinationisGiven = true;
			heuristicRecalculationCountDown = 0;
			currentCommand = move;
			jobStatus = returningToRefinery;
			
			myDropPosition = myRefinery.tileIndex[5] + 128;
			int xPosition = myDropPosition%128;
			int yPosition = 127 - myDropPosition/128;
			this.destinationX = xPosition*0.25f +0.125f;
			this.destinationY = yPosition*0.25f +0.125f;
			
			int insdieRefinery =  myRefinery.tileIndex[5];
			xPosition = insdieRefinery%128;
			yPosition = 127 - insdieRefinery/128;
			
			insideRefineryPositionX = xPosition*0.25f +0.125f;;
			insideRefineryPositionY = yPosition*0.25f +0.125f;
			
		}else{
			currentCommand = StandBy;
		}
	}
	
	public refinery findNearestRefinery(){
		refinery[] refineries = (refinery[])mainThread.theAssetManager.refineries;
		
		for(int i = 1; i < refineries.length; i++){
			for(int j = 0; j <refineries.length - i; j++){
				if(refineries[j] == null){
					refinery temp = refineries[j+1];
					refineries[j+1] = refineries[j];
					refineries[j] = temp;
				}else if(refineries[j +1] != null){
					float d1 = Math.abs(refineries[j].centre.x - centre.x) + Math.abs(refineries[j].centre.z - centre.z);
					float d2 = Math.abs(refineries[j + 1].centre.x - centre.x) + Math.abs(refineries[j+1].centre.z - centre.z);
					if(d1 > d2){
						refinery temp = refineries[j+1];
						refineries[j+1] = refineries[j];
						refineries[j] = temp;
					}
				}
			}
		}
		
		refinery nearestBusyRefinery = null;
		for(int i = 0; i < refineries.length; i++){
			if(refineries[i] != null){
				if(!refineries[i].isBusy && !refineries[i].droppingAreaIsFull(this) && refineries[i].currentHP >0 && (refineries[i].teamNo == teamNo)){	
					if(checkDistance(refineries[i]) > 4){
						if(nearestBusyRefinery == null)
							return refineries[i];
					}else{
						return refineries[i];
					}
				}
				if(nearestBusyRefinery == null  && (refineries[i].isBusy || refineries[i].droppingAreaIsFull(this)) && refineries[i].currentHP >0 && (refineries[i].teamNo == teamNo)){
					nearestBusyRefinery = refineries[i];
				}
			}
			
		}
			
		if(nearestBusyRefinery != null){
			waitingCount = 15;
			return nearestBusyRefinery;
		}
		
		return null;
	}
	
	public void goToTheNearestGoldMine(){
		int goldMineIndex = -1;
		double distance = 10;
		for(int i = 0; i < mainThread.theAssetManager.goldMines.length; i++){
			if(mainThread.theAssetManager.goldMines[i] == null)
				continue;
			
			double newDistance = getDistance(mainThread.theAssetManager.goldMines[i]);
			if(newDistance < distance  && mainThread.theAssetManager.goldMines[i].goldDeposite > 1){
				distance = newDistance;
				goldMineIndex = i;
			}
		}
		
		if(goldMineIndex != -1){
			myGoldMine = mainThread.theAssetManager.goldMines[goldMineIndex];
			//waitingCount = 15;
			returnToRefinery(null);
		}
	}
	
	public float checkDistance(solidObject o){
		return Math.abs(o.centre.x - centre.x) + Math.abs(o.centre.z - centre.z);
	}
	
	public void hold(){
		if(jobStatus < 4)
			currentCommand = StandBy;
	}
	
	public int getMaxHp(){return maxHP;}
	
}
