📄 unithandler.cpp
字号:
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 + -