Beispiel #1
0
void CUnitHandler::BuildTaskCreate(int id) {
	const UnitDef* newUnitDef = ai->cb->GetUnitDef(id);
	const UnitCategory category = ai->ut->GetCategory(id);
	const float3 pos = ai->cb->GetUnitPos(id);

	if ((!newUnitDef->movedata || category == CAT_DEFENCE) && !newUnitDef->canfly && category != CAT_LAST) {
		// this needs to change, so that it can make more stuff
		if (category >= CAT_LAST) {
			return;
		}

		BuildTask bt;
		bt.id = -1;

		std::list<TaskPlan>::iterator i;

		for (i = TaskPlans[category].begin(); i != TaskPlans[category].end(); i++) {
			if (pos.distance2D(i->pos) < 1.0f && newUnitDef == i->def) {
				bt.category = category;
				bt.id       = id;
				bt.pos      = i->pos;
				bt.def      = newUnitDef;

				std::list<BuilderTracker*> moveList;

				for (std::list<BuilderTracker*>::iterator builder = i->builderTrackers.begin(); builder != i->builderTrackers.end(); builder++) {
					moveList.push_back(*builder);
				}

				for (std::list<BuilderTracker*>::iterator builder = moveList.begin(); builder != moveList.end(); builder++) {
					TaskPlanRemove(*builder);
					BuildTaskAddBuilder(&bt, *builder);
				}

				// there can not be more than one found TaskPlan
				break;
			}
		}

		if (bt.id == -1) {
			// buildtask creation error (can happen if builder manages
			// to restart a dead building, or a human has taken control),
			// make one anyway
			std::stringstream msg;
				msg << "[CUnitHandler::BuildTaskCreate()][frame=" << ai->cb->GetCurrentFrame() << "]\n";
				msg << "\tBuildTask Creation Error for task with ID " << id << "\n";
			ai->GetLogger()->Log(msg.str());

			if (category == CAT_DEFENCE) {
				ai->dm->AddDefense(pos, newUnitDef);
			}

			bt.category = category;
			bt.id = id;
			bt.pos = pos;
			bt.def = newUnitDef;

			// if we have any friendly builders
			for (std::list<BuilderTracker*>::iterator i = BuilderTrackers.begin(); i != BuilderTrackers.end(); i++) {
				BuilderTracker* builderTracker = *i;

				// check what builder is doing
				const CCommandQueue* cq = ai->cb->GetCurrentUnitCommands(builderTracker->builderID);

				if (!cq->empty()) {
					Command c = cq->front();

					const bool b0 = (c.id == -newUnitDef->id && c.params[0] == pos.x && c.params[2] == pos.z); // at this pos
					const bool b1 = (c.id == CMD_REPAIR && c.params[0] == id); // at this unit (id)
					const bool b2 = (c.id == CMD_GUARD  && c.params[0] == id); // at this unit (id)
					const bool b3 = b0 || b1 || b2;

					if (b3) {
						if (builderTracker->buildTaskId != 0) {
							BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);

							if (buildTask->builderTrackers.size() > 1) {
								BuildTaskRemove(builderTracker);
							} else {
								// only builder of this thing, and now idle
								BuildTaskRemove(builderTracker);
							}
						}

						if (builderTracker->taskPlanId != 0) {
							GetTaskPlan(builderTracker->taskPlanId);
							TaskPlanRemove(builderTracker);
						}
						if (builderTracker->factoryId != 0) {
							FactoryBuilderRemove(builderTracker);
						}

						// this builder is now free
						if (builderTracker->idleStartFrame == -2) {
							IdleUnitRemove(builderTracker->builderID);
						}

						// add it to this task
						BuildTaskAddBuilder(&bt, builderTracker);

						msg.str("");
							msg << "\tadded builder " << builderTracker->builderID << " to";
							msg << " build-task with ID " << builderTracker->buildTaskId << "\n";
						ai->GetLogger()->Log(msg.str());
					}
				}
			}

			// add the task anyway
			BuildTasks[category].push_back(bt);
		}
		else {
			if (category == CAT_DEFENCE)
				ai->dm->AddDefense(pos,newUnitDef);

			BuildTasks[category].push_back(bt);
		}
	}
}
Beispiel #2
0
bool CUnitHandler::BuildTaskAddBuilder(int builderID, UnitCategory category) {
	assert(category < CAT_LAST);
	assert(builderID >= 0);
	assert(ai->GetUnit(builderID) != NULL);

	CUNIT* u = ai->GetUnit(builderID);
	BuilderTracker* builderTracker = GetBuilderTracker(builderID);

	const UnitDef* builderDef = ai->cb->GetUnitDef(builderID);
	const int frame = ai->cb->GetCurrentFrame();

	// make sure this builder is free
	const bool b1 = (builderTracker->taskPlanId == 0);
	const bool b2 = (builderTracker->buildTaskId == 0);
	const bool b3 = (builderTracker->factoryId == 0);
	const bool b4 = builderDef->canAssist;
	const bool b5 = (category == CAT_FACTORY && frame >= 18000);

	if (!b1 || !b2 || !b3 || !b4) {
		if (b5) {
			// note that FactoryBuilderAdd() asserts b1 through b4
			// immediately after BuildTaskAddBuilder() is tried and
			// fails in BuildUp(), so at least those must be true
			// (and so should b5 in most of the *A mods)

			std::stringstream msg;
				msg << "[CUnitHandler::BuildTaskAddBuilder()][frame=" << frame << "]\n";
				msg << "\tbuilder " << builderID << " not able to be added to CAT_FACTORY build-task\n";
				msg << "\tb1: " << b1 << ", b2: " << b2 << ", b3: " << b3;
				msg << ", b4: " << b4 << ", b5: " << b5;
			ai->GetLogger()->Log(msg.str());
		}

		return false;
	}

	// see if there are any BuildTasks that it can join
	if (BuildTasks[category].size() > 0) {
		float largestTime = 0.0f;
		std::list<BuildTask>::iterator task;
		std::list<BuildTask>::iterator bestTask;

		for (task = BuildTasks[category].begin(); task != BuildTasks[category].end(); task++) {
			float buildTime = ai->math->ETT(*task) - ai->math->ETA(builderID, ai->cb->GetUnitPos(task->id));

			if (buildTime > largestTime) {
				largestTime = buildTime;
				bestTask = task;
			}
		}

		if (largestTime > 0.0f) {
			BuildTaskAddBuilder(&*bestTask, builderTracker);
			u->Repair(bestTask->id);
			return true;
		}
	}

	// see if there any joinable TaskPlans
	if (TaskPlans[category].size() > 0) {
		float largestTime = 0.0f;
		std::list<TaskPlan>::iterator plan;
		std::list<TaskPlan>::iterator bestPlan;

		for (plan = TaskPlans[category].begin(); plan != TaskPlans[category].end(); plan++) {
			float buildTime = (plan->def->buildTime / plan->currentBuildPower) - ai->math->ETA(builderID, plan->pos);

			// must test if this builder can make this unit/building too
			if (buildTime > largestTime) {
				const std::vector<int>* canBuildList = &ai->ut->unitTypes[builderDef->id].canBuildList;
				const int buildListSize = canBuildList->size();

				for (int j = 0; j < buildListSize; j++) {
					if (canBuildList->at(j) == plan->def->id) {
						largestTime = buildTime;
						bestPlan = plan;
						break;
					}
				}
			}
		}

		if (largestTime > 10.0f) {
			assert(builderID >= 0);

			// bad, CUNIT::Build() uses TaskPlanCreate()
			// should we really give build orders here?
			// return u->Build(bestPlan->pos, bestPlan->def, -1);
			// TaskPlanCreate(builderID, bestPlan->pos, bestPlan->def);
			return true;
		}
	}

	if (b5) {
		std::stringstream msg;
			msg << "[CUnitHandler::BuildTaskAddBuilder()][frame=" << frame << "]\n";
			msg << "\tno joinable CAT_FACTORY build-tasks or task-plans for builder " << builderID;
		ai->GetLogger()->Log(msg.str());
	}

	return false;
}
bool CUnitHandler::BuildTaskAddBuilder(int builder, int category) {
	assert(category >= 0);
	assert(category < LASTCATEGORY);
	assert(builder >= 0);
	assert(ai->MyUnits[builder] != NULL);
	BuilderTracker* builderTracker = GetBuilderTracker(builder);

	// make sure this builder is free
	// KLOOTNOTE: no longer use assertions
	// since new code for extractor upgrading
	// (in CBuildUp) seems to trigger them?
	bool b1 = (builderTracker->taskPlanId == 0);
	bool b2 = (builderTracker->buildTaskId == 0);
	bool b3 = (builderTracker->factoryId == 0);
	bool b4 = (builderTracker->customOrderId == 0);

	if (!b1 || !b2 || !b3 || !b4) {
		return false;
	}

	// see if there are any BuildTasks that it can join
	if (BuildTasks[category].size()) {
		float largestime = 0;
		list<BuildTask>::iterator besttask;

		for (list<BuildTask>::iterator i = BuildTasks[category].begin(); i != BuildTasks[category].end(); i++) {
			float timebuilding = ai->math->ETT(*i) - ai->math->ETA(builder, ai->cb->GetUnitPos(i->id));
			if (timebuilding > largestime) {
				largestime = timebuilding;
				besttask = i;
			}
		}

		if (largestime > 0) {
			BuildTaskAddBuilder(&*besttask, builderTracker);
			ai->MyUnits[builder]->Repair(besttask->id);
			return true;
		}
	}

	if (TaskPlans[category].size()) {
			float largestime = 0;
			list<TaskPlan>::iterator besttask;

			for (list<TaskPlan>::iterator i = TaskPlans[category].begin(); i != TaskPlans[category].end(); i++) {
				float timebuilding = (i->def->buildTime / i->currentBuildPower) - ai->math->ETA(builder, i->pos);

				// must test if this builder can make this unit/building too
				if (timebuilding > largestime) {
					const UnitDef* builderDef = ai->cb->GetUnitDef(builder);
					vector<int>* canBuildList = &ai->ut->unitTypes[builderDef->id].canBuildList;
					int size = canBuildList->size();
					int thisBuildingID = i->def->id;

					for (int j = 0; j < size; j++) {
						if (canBuildList->at(j) == thisBuildingID) {
							largestime = timebuilding;
							besttask = i;
							break;
						}
					}
				}
			}

			if (largestime > 10) {
				assert(builder >= 0);
				assert(ai->MyUnits[builder] !=  NULL);
				// this is bad, as ai->MyUnits[builder]->Build uses TaskPlanCreate()
				ai->MyUnits[builder]->Build(besttask->pos, besttask->def, -1);
				return true;
		}
	}

	return false;
}
Beispiel #4
0
void CUnitHandler::DecodeOrder(BuilderTracker* builderTracker, bool reportError) {
	const int            frame     = ai->cb->GetCurrentFrame();
	const int            builderID = builderTracker->builderID;
	const CCommandQueue* builderQ  = ai->cb->GetCurrentUnitCommands(builderID);

	if (builderQ->size() > 0) {
		// builder has orders
		const Command* c   = &builderQ->front();
		const int      n   = c->params.size();
		const int      cID = c->id;

		if (builderQ->size() == 2 && cID == CMD_MOVE) {
			// it might have a move order before the real order,
			// take command nr. 2 if nr. 1 is a move order
			c = &builderQ->back();
		}

		if (reportError) {
			std::stringstream msg;
				msg << "[CUnitHandler::DecodeOrder()][frame=" << frame << "]\n";
				msg << "\tbuilder " << builderID << " claimed idle, but has";
				msg << " command " << cID << " with " << n << " parameters";
				msg << " (params[0]: " << ((n > 0)? c->params[0]: -1) << ")\n";
			ai->GetLogger()->Log(msg.str());
		}

		if (cID < 0) {
			assert(n >= 3);

			// it's building a unit
			float3 newUnitPos;
			newUnitPos.x = c->params[0];
			newUnitPos.y = c->params[1];
			newUnitPos.z = c->params[2];

			const UnitDef* newUnitDef = ai->ut->unitTypes[-cID].def;
			// make sure that no BuildTasks exists there
			BuildTask* buildTask = BuildTaskExist(newUnitPos, newUnitDef);

			if (buildTask) {
				BuildTaskAddBuilder(buildTask, builderTracker);
			} else {
				// make a new TaskPlan (or join an existing one)
				TaskPlanCreate(builderID, newUnitPos, newUnitDef);
			}
		}

		if (cID == CMD_REPAIR) {
			assert(n >= 1);

			// it's repairing, find the unit being repaired
			int guardingID = int(c->params[0]);
			bool found = false;

			UnitCategory cat = ai->ut->GetCategory(guardingID);
			std::list<BuildTask>::iterator i;

			if (cat == CAT_LAST) {
				return;
			}

			for (i = BuildTasks[cat].begin(); i != BuildTasks[cat].end(); i++) {
				if (i->id == guardingID) {
					// whatever the old order was, update it now
					bool hit = false;
					if (builderTracker->buildTaskId != 0) {
						hit = true;
						// why is this builder idle?
						BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);

						if (buildTask->builderTrackers.size() > 1) {
							BuildTaskRemove(builderTracker);
						} else {
							// only builder of this thing, and now idle?
							BuildTaskRemove(builderTracker);
						}
					}
					if (builderTracker->taskPlanId != 0) {
						assert(!hit);
						hit = true;
						TaskPlanRemove(builderTracker);
					}
					if (builderTracker->factoryId != 0) {
						assert(!hit);
						hit = true;
						FactoryBuilderRemove(builderTracker);
					}

					BuildTask* bt = &*i;
					BuildTaskAddBuilder(bt, builderTracker);
					found = true;
				}
			}
			if (!found) {
				// not found, just make a custom order
				builderTracker->idleStartFrame = -1;
			}
		}
	} else {
		// error: this function needs a builder with orders
		// should not be possible because IdleUnitUpdate()
		// calls us only if a unit's command-queue is NOT
		// empty?
		// assert(false);
		std::stringstream msg;
			msg << "[CUnitHandler::DecodeOrder()][frame=" << frame << "]\n";
			msg << "\tbuilder " << builderID << " should not have an empty queue!\n";
		ai->GetLogger()->Log(msg.str());
	}
}
void CUnitHandler::BuildTaskCreate(int id) {
	const UnitDef* newUnitDef = ai->cb->GetUnitDef(id);
	int category = ai->ut->GetCategory(id);
	float3 pos = ai->cb->GetUnitPos(id);

	if ((!newUnitDef->movedata || category == CAT_DEFENCE) && !newUnitDef->canfly && category != -1) {
		// this needs to change, so that it can make more stuff
		if (category == -1)
			return;

		assert(category >= 0);
		assert(category < LASTCATEGORY);

		BuildTask bt;
		bt.id = -1;

		redo:
		for (list<TaskPlan>::iterator i = TaskPlans[category].begin(); i != TaskPlans[category].end(); i++) {
			if(pos.distance2D(i->pos) < 1 && newUnitDef == i->def){
				assert(bt.id == -1); // There can not be more than one TaskPlan that is found;
				bt.category = category;
				bt.id = id;
				bt.pos = i->pos;
				bt.def = newUnitDef;
				list<BuilderTracker*> moveList;

				for (list<BuilderTracker*>::iterator builder = i->builderTrackers.begin(); builder != i->builderTrackers.end(); builder++) {
					moveList.push_back(*builder);
				}

				for (list<BuilderTracker*>::iterator builder = moveList.begin(); builder != moveList.end(); builder++) {
					TaskPlanRemove(*builder);
					BuildTaskAddBuilder(&bt, *builder);
				}

				goto redo;
			}
		}

		if (bt.id == -1) {
			// buildtask creation error (can happen if builder manages
			// to restart a dead building, or a human has taken control),
			// make one anyway
			bt.category = category;
			bt.id = id;

			if (category == CAT_DEFENCE)
				ai->dm->AddDefense(pos,newUnitDef);

			bt.pos = pos;
			bt.def = newUnitDef;
			char text[512];
			sprintf(text, "BuildTask Creation Error: %i", id);
			int num = BuilderTrackers.size();

			if (num == 0) {
				// no friendly builders found
			} else {
				// iterate over the list and find the builders
				for (list<BuilderTracker*>::iterator i = BuilderTrackers.begin(); i != BuilderTrackers.end(); i++) {
					BuilderTracker* builderTracker = *i;

					// check what builder is doing
					const CCommandQueue* mycommands = ai->cb->GetCurrentUnitCommands(builderTracker->builderID);
					if (mycommands->size() > 0) {
						Command c = mycommands->front();

						if ((c.id == -newUnitDef->id && c.params[0] == pos.x && c.params[2] == pos.z) // at this pos
							|| (c.id == CMD_REPAIR  && c.params[0] == id)  // at this unit (id)
							|| (c.id == CMD_GUARD  && c.params[0] == id)) // at this unit (id)
						{
							if (builderTracker->buildTaskId != 0) {
								BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);

								if (buildTask->builderTrackers.size() > 1) {
									BuildTaskRemove(builderTracker);
								} else {
									// only builder of this thing, and now idle
									BuildTaskRemove(builderTracker);
								}
							}

							if (builderTracker->taskPlanId != 0) {
								GetTaskPlan(builderTracker->taskPlanId);
								TaskPlanRemove(builderTracker);
							}
							if (builderTracker->factoryId != 0) {
								FactoryBuilderRemove(builderTracker);
							}
							if (builderTracker->customOrderId != 0) {
								builderTracker->customOrderId = 0;
							}

							// this builder is now free
							if (builderTracker->idleStartFrame == -2)
								IdleUnitRemove(builderTracker->builderID);

							// add it to this task
							BuildTaskAddBuilder(&bt, builderTracker);
							sprintf(text, "Added builder %i to buildTaskId %i (human order?)", builderTracker->builderID, builderTracker->buildTaskId);
						}
					}
				}
			}

			// add the task anyway
			BuildTasks[category].push_back(bt);
		}
		else {
			if (category == CAT_DEFENCE)
				ai->dm->AddDefense(pos,newUnitDef);

			BuildTasks[category].push_back(bt);
		}
	}
}
void CUnitHandler::DecodeOrder(BuilderTracker* builderTracker, bool reportError) {
	// take a look and see what it's doing
	const CCommandQueue* mycommands = ai->cb->GetCurrentUnitCommands(builderTracker->builderID);

	if (mycommands->size() > 0) {
		// builder has orders
		const Command* c = &mycommands->front();
		if (mycommands->size() == 2 && c->id == CMD_MOVE) { //&& (c->id == CMD_MOVE || c->id == CMD_RECLAIM))
			// it might have a move order before the real order,
			// take command nr. 2 if nr. 1 is a move order
			c = &mycommands->back();
		}

		if (reportError) {
			char text[512];
			sprintf(text, "builder %i: claimed idle, but has command c->id: %i, c->params[0]: %f", builderTracker->builderID, c->id, c->params[0]);
		}

		if (c->id < 0) {
			// it's building a unit
			float3 newUnitPos;
			newUnitPos.x = c->params[0];
			newUnitPos.y = c->params[1];
			newUnitPos.z = c->params[2];
			// c.id == -newUnitDef->id
			const UnitDef* newUnitDef = ai->ut->unitTypes[-c->id].def;
			// make sure that no BuildTasks exists there
			BuildTask* buildTask = BuildTaskExist(newUnitPos, newUnitDef);

			if (buildTask) {
				BuildTaskAddBuilder(buildTask, builderTracker);
			} else {
				// make a new TaskPlan (or join an existing one)
				TaskPlanCreate(builderTracker->builderID, newUnitPos, newUnitDef);
			}
		}

		if (c->id == CMD_REPAIR) {
			// it's repairing
			int guardingID = int(c->params[0]);
			// find the unit being repaired
			int category = ai->ut->GetCategory(guardingID);
			bool found = false;

			if (category == -1)
				return;

			for (list<BuildTask>::iterator i = BuildTasks[category].begin(); i != BuildTasks[category].end(); i++) {
				if (i->id == guardingID) {
					// whatever the old order was, update it now
					bool hit = false;
					if (builderTracker->buildTaskId != 0) {
						hit = true;
						// why is this builder idle?
						BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);

						if (buildTask->builderTrackers.size() > 1) {
							BuildTaskRemove(builderTracker);
						} else {
							// only builder of this thing, and now idle?
							BuildTaskRemove(builderTracker);
						}
					}
					if (builderTracker->taskPlanId != 0) {
						assert(!hit);
						hit = true;
						TaskPlanRemove(builderTracker);
					}
					if (builderTracker->factoryId != 0) {
						assert(!hit);
						hit = true;
						FactoryBuilderRemove(builderTracker);
					}
					if (builderTracker->customOrderId != 0) {
						assert(!hit);
						hit = true;
						builderTracker->customOrderId = 0;
					}
					BuildTask* bt = &*i;
					BuildTaskAddBuilder(bt, builderTracker);
					found = true;
				}
			}
			if (!found) {
				// not found, just make a custom order
				builderTracker->customOrderId = taskPlanCounter++;
				builderTracker->idleStartFrame = -1;
			}
		}
	}
	else {
		// error: this function needs a builder with orders
		assert(false);
	}
}
bool CUnitHandler::BuildTaskAddBuilder (int builder, int category)
{
	//L("BuildTaskAddBuilder: " << builder);
	assert(category >= 0);
	assert(category < LASTCATEGORY);
	assert(builder >= 0);
	assert(ai->MyUnits[builder] !=  NULL);
	BuilderTracker * builderTracker = GetBuilderTracker(builder);
	// Make shure this builder is free:
	assert(builderTracker->taskPlanId == 0);
	assert(builderTracker->buildTaskId == 0);
	assert(builderTracker->factoryId == 0);
	assert(builderTracker->customOrderId == 0);
	
	// See if there are any BuildTasks that it can join
	if(BuildTasks[category]->size()){
		float largestime = 0;
		list<BuildTask>::iterator besttask;
		for(list<BuildTask>::iterator i = BuildTasks[category]->begin(); i != BuildTasks[category]->end(); i++){
			float timebuilding = ai->math->ETT(*i) - ai->math->ETA(builder,ai->cb->GetUnitPos(i->id));
			if(timebuilding > largestime){
				largestime = timebuilding;
				besttask = i;
			}
		}
		if(largestime > 0){
			BuildTaskAddBuilder(&*besttask, builderTracker);
			ai->MyUnits[builder]->Repair(besttask->id);
			return true;
		}
	}
	// HACK^2    Korgothe...   this thing dont exist...
	if(TaskPlans[category]->size())
	{
			//L("TaskPlans[category]->size()");
			float largestime = 0;
			list<TaskPlan>::iterator besttask;
			int units[5000];
			//redo:
			for(list<TaskPlan>::iterator i = TaskPlans[category]->begin(); i != TaskPlans[category]->end(); i++){
				float timebuilding = (i->def->buildTime / i->currentBuildPower ) - ai->math->ETA(builder,i->pos);
				
				////L("timebuilding: " << timebuilding << " of " << i->def->humanName);
				// Must test if this builder can make this unit/building too
				if(timebuilding > largestime){
					const UnitDef *buildeDef = ai->cb->GetUnitDef(builder);
					vector<int> * canBuildList = &ai->ut->unittypearray[buildeDef->id].canBuildList;
					int size = canBuildList->size();
					int thisBuildingID = i->def->id;
					//bool canBuild = false; // Not needed, 
					for(int j = 0; j < size; j++)
					{
						if(canBuildList->at(j) == thisBuildingID)
						{
							//canBuild = true;
							largestime = timebuilding;
							besttask = i;
							break;
						}
					}
				}
				
				
				int num = ai->cb->GetFriendlyUnits(units, i->pos,200); //returns all friendly units within radius from pos
				for(int j = 0; j < num; j++)
				{
					////L("Found unit at spot");
					
					if((ai->cb->GetUnitDef(units[j]) == i->def) && (ai->cb->GetUnitPos(units[j]).distance2D(i->pos)) < 1 )
					{
						// HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
						//L("if((ai->cb->GetUnitDef(units[j]) == i->def) && (ai->cb->GetUnitPos(units[j]).distance2D(i->pos)) < 1 )");
						//L("TODO: Kill this TaskPlan -- this is BAD -- its on a spot where a building is");
						// TODO: Kill this TaskPlan
						// But not here... as that will mess up the iterator
						
						
						//assert(false);
						//TaskPlans[category]->erase(i);
						//largestime = 0;
						//goto redo;
					}
				}
				
			}
			//L("largestime: " << largestime);
			
			if(largestime > 10){
				//L("joining the building of " << besttask->def->humanName);
				
				assert(builder >= 0);
				assert(ai->MyUnits[builder] !=  NULL);
				// This is bad. as ai->MyUnits[builder]->Build use TaskPlanCreate()
				// It will work however 
				ai->MyUnits[builder]->Build(besttask->pos, besttask->def);
				return true;
		}
	}
	
	
	return false;
}
void CUnitHandler::BuildTaskCreate(int id) {
	const UnitDef* newUnitDef = ai->cb->GetUnitDef(id);
	int category = ai->ut->GetCategory(id);
	float3 pos = ai->cb->GetUnitPos(id);
	if((!newUnitDef->movedata  || category == CAT_DEFENCE) && !newUnitDef->canfly && category != -1){ // This thing need to change, so that it can make more stuff
		
		// TODO: Hack fix
		if(category == -1)
			return;
		assert(category >= 0);
		assert(category < LASTCATEGORY);
		
		BuildTask bt;
		bt.id = -1;
		//int killplan;
		//list<TaskPlan>::iterator killplan;
		redo:
		for(list<TaskPlan>::iterator i = TaskPlans[category]->begin(); i != TaskPlans[category]->end(); i++){
			if(pos.distance2D(i->pos) < 1 && newUnitDef == i->def){
				assert(bt.id == -1); // There can not be more than one TaskPlan that is found;
				bt.category = category;
				bt.id = id;
				bt.pos = i->pos;
				bt.def = newUnitDef;
				list<BuilderTracker*> moveList;
				for(list<BuilderTracker*>::iterator builder = i->builderTrackers.begin(); builder != i->builderTrackers.end(); builder++) {
					moveList.push_back(*builder);
					//L("Marking builder " << (*builder)->builderID << " for removal, from plan " << i->def->humanName);
				}
				for(list<BuilderTracker*>::iterator builder = moveList.begin(); builder != moveList.end(); builder++) {
					TaskPlanRemove(*builder);
					BuildTaskAddBuilder(&bt, *builder);
				}
				//bt.builders.push_back(i->builder);
				//killplan = i->builder;
				// This plan is gone now
				// Test it by redoing all:
				goto redo; // This is a temp
			}
		}
		if(bt.id == -1){
			//L("*******BuildTask Creation Error!*********");
			// This can happen.
			// Either a builder manges to restart a dead building, or a human have taken control...
			// Make a BuildTask anyway
			bt.category = category;
			bt.id = id;
			if(category == CAT_DEFENCE)
				ai->dm->AddDefense(pos,newUnitDef);
			bt.pos = pos;
			bt.def = newUnitDef;
			char text[512];
			sprintf(text, "BuildTask Creation Error: %i", id);
			AIHCAddMapPoint amp;
			amp.label = text;
			amp.pos = pos;
			////ai->cb->HandleCommand(&amp);
			// Try to find workers that nearby:
			int num = BuilderTrackers.size();
			
			if(num == 0)
			{
				// Well what now ??? 
				//L("Didnt find any friendly builders");
			} else
			{
				// Iterate over the list and find the builders
				for(list<BuilderTracker*>::iterator i = BuilderTrackers.begin(); i != BuilderTrackers.end(); i++)
				{
					BuilderTracker* builderTracker = *i;
					// Now take a look, and see what its doing:
					const deque<Command>* mycommands = ai->cb->GetCurrentUnitCommands(builderTracker->builderID);
					if(mycommands->size() > 0)
					{
						// It have orders
						Command c = mycommands->front();
						//L("builder: " << builderTracker->builderID);
						//L("c.id: " << c.id);
						//L("c.params[0]: " <<  c.params[0]);
						if( (c.id == -newUnitDef->id && c.params[0] == pos.x && c.params[2] == pos.z) // Its at this pos
							|| (c.id == CMD_REPAIR  && c.params[0] == id)  // Its at this unit (id)
							|| (c.id == CMD_GUARD  && c.params[0] == id) ) // Its at this unit (id)
						{
							// Its making this unit
							// Remove the unit from its current job:
							bool hit = false;
							if(builderTracker->buildTaskId != 0)
							{
								// Hmm, why is this builder idle ???
//								bool hit = true;
								BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);
								if(buildTask->builderTrackers.size() > 1)
								{
									BuildTaskRemove(builderTracker);
								}
								else
								{
									// This is the only builder of this thing, and now its idle...
									BuildTaskRemove(builderTracker); // IS this smart at all ???
								}
							}
							if(builderTracker->taskPlanId != 0)
							{
								assert(!hit);
//								bool hit = true;
								// Hmm, why is this builder idle ???
								// 
//								TaskPlan* taskPlan = GetTaskPlan(builderTracker->taskPlanId);
								TaskPlanRemove(builderTracker);
							}
							if(builderTracker->factoryId != 0)
							{
								assert(!hit);
//								bool hit = true;
								FactoryBuilderRemove(builderTracker);
							}
							if(builderTracker->customOrderId != 0)
							{
								assert(!hit);
//								bool hit = true;
								builderTracker->customOrderId = 0;
							}
							// This builder is now free.
							if(builderTracker->idleStartFrame == -2)
								IdleUnitRemove(builderTracker->builderID); // It was in the idle list
							// Add it to this task
							//L("Added builder " << builderTracker->builderID << " to this new unit buildTask");
							BuildTaskAddBuilder(&bt, builderTracker);
							sprintf(text, "Added builder %i: to buildTaskId: %i (human order?)", builderTracker->builderID, builderTracker->buildTaskId);
							AIHCAddMapPoint amp2;
							amp2.label = text;
							amp2.pos = ai->cb->GetUnitPos(builderTracker->builderID);
							////ai->cb->HandleCommand(&amp2);
						} else
						{
							// This builder have other orders.
						}
						
					} else
					{
						// This builder is without orders (idle)
					}
					
				}
			
			}
			// Add the task anyway
			BuildTasks[category]->push_back(bt);
			
		}
		else{
			if(category == CAT_DEFENCE)
				ai->dm->AddDefense(pos,newUnitDef);
			BuildTasks[category]->push_back(bt);
			//TaskPlanRemove(*killplan); // fix
		}
	}
}
void CUnitHandler::DecodeOrder(BuilderTracker* builderTracker, bool reportError) {
	reportError = reportError;
	// If its without orders then try to find the lost command
	
	// TODO: All of it!!!!!!!!!!!!!!
	// Now take a look, and see what its doing:
	const deque<Command>* mycommands = ai->cb->GetCurrentUnitCommands(builderTracker->builderID);
	if(mycommands->size() > 0)
	{
		// It have orders
		const Command* c = &mycommands->front();
		if(mycommands->size() == 2 && c->id == CMD_MOVE)//&& (c->id == CMD_MOVE || c->id == CMD_RECLAIM))  
		{
			// Hmm, it might have a move order before the real order
			// Take command nr. 2 if nr.1 is a move order
			c = &mycommands->back();
		}
		
		
		//L("idle builder: " << builderTracker->builderID);
		//L("c->id: " << c->id);
		//L("c->params[0]: " <<  c->params[0]);
		char text[512];
		sprintf(text, "builder %i: was clamed idle, but it have a command c->id: %i, c->params[0]: %f", builderTracker->builderID, c->id, c->params[0]);
		AIHCAddMapPoint amp;
		amp.label = text;
		amp.pos = ai->cb->GetUnitPos(builderTracker->builderID);
		////ai->cb->HandleCommand(&amp);
		if(c->id < 0) // Its building a unit
		{
			float3 newUnitPos;
			newUnitPos.x = c->params[0];
			newUnitPos.y = c->params[1];
			newUnitPos.z = c->params[2];
			// c.id == -newUnitDef->id
			const UnitDef* newUnitDef = ai->ut->unittypearray[-c->id].def;
			// Now make shure that no BuildTasks exists there 
			BuildTask* buildTask = BuildTaskExist(newUnitPos, newUnitDef);
			if(buildTask)
			{
				BuildTaskAddBuilder(buildTask, builderTracker);
			}
			else // Make a new TaskPlan (or join an existing one)
				TaskPlanCreate(builderTracker->builderID, newUnitPos, newUnitDef);

		}
		if(c->id == CMD_REPAIR)  // Its repairing    ( || c.id == CMD_GUARD)
		{
			int guardingID = int(c->params[0]);
			// Find the unit its repairng
			int category = ai->ut->GetCategory(guardingID);
			if(category == -1)
				return; // This is bad....
			bool found = false;
			for(list<BuildTask>::iterator i = BuildTasks[category]->begin(); i != BuildTasks[category]->end(); i++){
				if(i->id == guardingID)
				{
					// Whatever the old order was, update it now...
					bool hit = false;
					if(builderTracker->buildTaskId != 0)
					{
						hit = true;
						// Hmm, why is this builder idle ???
						BuildTask* buildTask = GetBuildTask(builderTracker->buildTaskId);
						if(buildTask->builderTrackers.size() > 1)
						{
							BuildTaskRemove(builderTracker);
						}
						else
						{
							// This is the only builder of this thing, and now its idle...
							BuildTaskRemove(builderTracker); // IS this smart at all ???
						}
					}
					if(builderTracker->taskPlanId != 0)
					{
						assert(!hit);
						hit = true;
						TaskPlanRemove(builderTracker);
						
						//return;
					}
					if(builderTracker->factoryId != 0)
					{
						assert(!hit);
						hit = true;
						FactoryBuilderRemove(builderTracker);
					}
					if(builderTracker->customOrderId != 0)
					{
						assert(!hit);
						hit = true;
						builderTracker->customOrderId = 0;
					}
					BuildTask* bt = &*i;
					//L("Adding builder to BuildTask " << bt->id << ": " << ai->cb->GetUnitDef(bt->id)->humanName);
					BuildTaskAddBuilder(bt, builderTracker);
					found = true;
				}
			}
			if(found == false)
			{
				// Not found, just make a custom order
				//L("Not found, just make a custom order");
				builderTracker->customOrderId = taskPlanCounter++;
				builderTracker->idleStartFrame = -1; // Its in use now
			}
		}
	}
	else
	{
		// Error: this function needs a builder with orders
		//L("Error: this function needs a builder with orders");
		assert(false);
	}
}