⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unithandler.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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);
	}
}



void CUnitHandler::IdleUnitRemove(int unit) {
	int category = ai->ut->GetCategory(unit);

	if (category != -1) {
		IdleUnits[category].remove(unit);

		if (category == CAT_BUILDER) {
			BuilderTracker* builderTracker = GetBuilderTracker(unit);
			builderTracker->idleStartFrame = -1;

			if (builderTracker->commandOrderPushFrame == -2) {
				// bad
			}

			// update the order start frame
			builderTracker->commandOrderPushFrame = ai->cb->GetCurrentFrame();
			// assert(builderTracker->buildTaskId == 0);
			// assert(builderTracker->taskPlanId == 0);
			// assert(builderTracker->factoryId == 0);
		}

		list<integer2>::iterator tempunit;
		bool foundit = false;

		for (list<integer2>::iterator i = Limbo.begin(); i != Limbo.end(); i++) {
			if (i->x == unit) {
				tempunit = i;
				foundit = true;
			}
		}

		if (foundit)
			Limbo.erase(tempunit);
	}
}


int CUnitHandler::GetIU(int category) {
	assert(IdleUnits[category].size() > 0);
	int unitID = IdleUnits[category].front();

	// move the returned unitID to the back
	// of the list, so CBuildUp::FactoryCycle()
	// doesn't keep examining the same factory
	// if a build order fails and we have more
	// than one idle factory
	IdleUnits[category].pop_front();
	IdleUnits[category].push_back(unitID);

	return unitID;
}

int CUnitHandler::NumIdleUnits(int category) {
	assert(category >= 0 && category < LASTCATEGORY);
	IdleUnits[category].sort();
	IdleUnits[category].unique();
	return IdleUnits[category].size();
}




void CUnitHandler::MMakerAdd(int unit) {
	metalMaker->Add(unit);
}
void CUnitHandler::MMakerRemove(int unit) {
	metalMaker->Remove(unit);
}

void CUnitHandler::MMakerUpdate(int frame) {
	metalMaker->Update(frame);
}




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::BuildTaskRemove(int id) {
	int category = ai->ut->GetCategory(id);

	if (category == -1)
		return;

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

	if (category != -1) {
		list<BuildTask>::iterator killtask;
		bool found = false;

		for (list<BuildTask>::iterator i = BuildTasks[category].begin(); i != BuildTasks[category].end(); i++) {
			if (i->id == id) {
				killtask = i;
				assert(!found);
				found = true;
			}
		}
		if (found) {
			// remove the builders from this BuildTask
			list<BuilderTracker*> removeList;
			for (list<BuilderTracker*>::iterator builder = killtask->builderTrackers.begin(); builder != killtask->builderTrackers.end(); builder++) {
				removeList.push_back(*builder);
			}
			for (list<BuilderTracker*>::iterator builder = removeList.begin(); builder != removeList.end(); builder++) {
				BuildTaskRemove(*builder);
			}

			BuildTasks[category].erase(killtask);
		}
	}
}


BuilderTracker* CUnitHandler::GetBuilderTracker(int builder) {
	for (list<BuilderTracker*>::iterator i = BuilderTrackers.begin(); i != BuilderTrackers.end(); i++) {
		if ((*i)->builderID == builder) {
			return (*i);
		}
	}

	// this better not happen
	assert(false);
	return 0;
}


void CUnitHandler::BuildTaskRemove(BuilderTracker* builderTracker) {
	if (builderTracker->buildTaskId == 0) {
		assert(false);
		return;
	}
	int category = ai->ut->GetCategory(builderTracker->buildTaskId);
	// TODO: Hack fix
	if (category == -1)
		return;

	assert(category >= 0);
	assert(category < LASTCATEGORY);
	assert(builderTracker->buildTaskId != 0);
	assert(builderTracker->taskPlanId == 0);
	assert(builderTracker->factoryId == 0);
	assert(builderTracker->customOrderId == 0);
	// list<BuildTask>::iterator killtask;
	bool found = false;
	bool found2 = false;

	for (list<BuildTask>::iterator i = BuildTasks[category].begin(); i != BuildTasks[category].end(); i++) {
		if (i->id == builderTracker->buildTaskId){
			// killtask = i;
			assert(!found);
			for (list<int>::iterator builder = i->builders.begin(); builder != i->builders.end(); builder++) {
				if (builderTracker->builderID == *builder) {
					assert(!found2);
					i->builders.erase(builder);
					builderTracker->buildTaskId = 0;
					found2 = true;
					break;
				}
			}
			for (list<BuilderTracker*>::iterator builder = i->builderTrackers.begin(); builder != i->builderTrackers.end(); builder++) {
				if (builderTracker == *builder) {
					assert(!found);
					i->builderTrackers.erase(builder);
					builderTracker->buildTaskId = 0;
 					// give it time to change command
					builderTracker->commandOrderPushFrame = ai->cb->GetCurrentFrame();
					found = true;
					break;
				}
			}

		}
	}

	assert(found);
}



void CUnitHandler::BuildTaskAddBuilder(BuildTask* buildTask, BuilderTracker* builderTracker) {
	buildTask->builders.push_back(builderTracker->builderID);
	buildTask->builderTrackers.push_back(builderTracker);
	buildTask->currentBuildPower += ai->cb->GetUnitDef(builderTracker->builderID)->buildSpeed;
	assert(builderTracker->buildTaskId == 0);
	assert(builderTracker->taskPlanId == 0);
	assert(builderTracker->factoryId == 0);
	assert(builderTracker->customOrderId == 0);
	builderTracker->buildTaskId = buildTask->id;
}

BuildTask* CUnitHandler::GetBuildTask(int buildTaskId) {
	for (int k = 0; k < LASTCATEGORY; k++) {
		for (list<BuildTask>::iterator i = BuildTasks[k].begin(); i != BuildTasks[k].end(); i++) {
			if (i->id == buildTaskId)
				return  &*i;
		}
	}

	// this better not happen
	assert(false);
	return 0;
}



BuildTask* CUnitHandler::BuildTaskExist(float3 pos, const UnitDef* builtdef) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -