void CFactory::AssignBuildeeOrders(CUnit* unit) { const CFactoryCAI* facAI = (CFactoryCAI*) commandAI; const CCommandQueue& newUnitCmds = facAI->newUnitCommands; if (newUnitCmds.empty()) { SendToEmptySpot(unit); return; } // HACK: when a factory has a rallypoint set far enough away // to trigger the non-admissable path estimators, we want to // avoid units getting stuck inside by issuing them an extra // move-order. However, this order can *itself* cause the PF // system to consider the path blocked if the extra waypoint // falls within the factory's confines, so use a wide berth. const float xs = unitDef->xsize * SQUARE_SIZE * 0.5f; const float zs = unitDef->zsize * SQUARE_SIZE * 0.5f; float tmpDst = 2.0f; float3 tmpPos = unit->pos + (frontdir * this->radius * tmpDst); if (buildFacing == FACING_NORTH || buildFacing == FACING_SOUTH) { while ((tmpPos.z >= unit->pos.z - zs && tmpPos.z <= unit->pos.z + zs)) { tmpDst += 0.5f; tmpPos = unit->pos + (frontdir * this->radius * tmpDst); } } else { while ((tmpPos.x >= unit->pos.x - xs && tmpPos.x <= unit->pos.x + xs)) { tmpDst += 0.5f; tmpPos = unit->pos + (frontdir * this->radius * tmpDst); } } Command c; c.id = CMD_MOVE; c.params.push_back(tmpPos.x); c.params.push_back(tmpPos.y); c.params.push_back(tmpPos.z); unit->commandAI->GiveCommand(c); /* const float3 tmpWaypoint = curBuild->pos + frontdir * (this->radius * 2.5f); Command c; c.id = CMD_MOVE; c.params.push_back(tmpWaypoint.x); c.params.push_back(tmpWaypoint.y); c.params.push_back(tmpWaypoint.z); unit->commandAI->GiveCommand(c); */ for (CCommandQueue::const_iterator ci = newUnitCmds.begin(); ci != newUnitCmds.end(); ++ci) { c = *ci; c.options |= SHIFT_KEY; unit->commandAI->GiveCommand(c); } }
void CFactory::Update() { if(beingBuilt){ CUnit::Update(); return; } if(quedBuild && inBuildStance){ std::vector<long> args; args.push_back(0); cob->Call("QueryBuildInfo",args); float3 relBuildPos=localmodel->GetPiecePos(args[0]); float3 buildPos=pos + frontdir*relBuildPos.z + updir*relBuildPos.y + rightdir*relBuildPos.x; bool canBuild=true; std::vector<CUnit*> units=qf->GetUnitsExact(buildPos,16); for(std::vector<CUnit*>::iterator ui=units.begin();ui!=units.end();++ui){ if((*ui)!=this) canBuild=false; } if(canBuild){ quedBuild=false; CUnit* b=unitLoader.LoadUnit(nextBuild,buildPos+float3(0.01,0.01,0.01),team,true); AddDeathDependence(b); curBuild=b; cob->Call("StartBuilding"); if(unitDef->sounds.build.id) sound->PlaySound(unitDef->sounds.build.id, pos, unitDef->sounds.build.volume); } else { helper->BuggerOff(buildPos-float3(0.01,0,0.02),radius+8); } } if(curBuild && !beingBuilt){ lastBuild=gs->frameNum; std::vector<long> args; args.push_back(0); cob->Call("QueryBuildInfo",args); CMatrix44f mat=localmodel->GetPieceMatrix(args[0]); int h=GetHeadingFromVector(mat[2],mat[10]); curBuild->heading=h; // if(curBuild->unitDef->canfly){ //hack to get naval air plant to work correctly, how to do it correctly ? float3 relBuildPos=localmodel->GetPiecePos(args[0]); float3 buildPos=pos + frontdir*relBuildPos.z + updir*relBuildPos.y + rightdir*relBuildPos.x; curBuild->pos=buildPos; if(curBuild->floatOnWater) curBuild->pos.y=ground->GetHeight(buildPos.x,buildPos.z)-curBuild->unitDef->waterline; curBuild->midPos=curBuild->pos+UpVector*curBuild->relMidPos.y; // } if(curBuild->AddBuildPower(buildSpeed,this)){ std::vector<long> args; args.push_back(0); cob->Call("QueryNanoPiece",args); float3 relWeaponFirePos=localmodel->GetPiecePos(args[0]); float3 weaponPos=pos + frontdir*relWeaponFirePos.z + updir*relWeaponFirePos.y + rightdir*relWeaponFirePos.x; float3 dif=curBuild->midPos-weaponPos; float l=dif.Length(); dif/=l; dif+=gs->randVector()*0.15f; new CGfxProjectile(weaponPos,dif,l,float3(0.2f,0.7f,0.2f)); } else { if(!curBuild->beingBuilt){ if(group) curBuild->SetGroup(group); Command c; c.id=CMD_MOVE_STATE; c.options=0; c.params.push_back(moveState); curBuild->commandAI->GiveCommand(c); c.params.clear(); c.id=CMD_FIRE_STATE; c.params.push_back(fireState); curBuild->commandAI->GiveCommand(c); if(curBuild->commandAI->commandQue.empty() || (dynamic_cast<CMobileCAI*>(curBuild->commandAI) && ((CMobileCAI*)curBuild->commandAI)->unimportantMove)){ if(((CFactoryCAI*)commandAI)->newUnitCommands.empty()){ SendToEmptySpot(curBuild); } else { for(std::deque<Command>::iterator ci=((CFactoryCAI*)commandAI)->newUnitCommands.begin();ci!=((CFactoryCAI*)commandAI)->newUnitCommands.end();++ci) curBuild->commandAI->GiveCommand(*ci); } } StopBuild(); } } } if(lastBuild+200 < gs->frameNum && !quedBuild && opening && uh->CanCloseYard(this)){ readmap->CloseBlockingYard(this); opening=false; cob->Call(COBFN_Deactivate); } CBuilding::Update(); }
void CFactory::Update() { if (beingBuilt) { // factory under construction CUnit::Update(); return; } if (quedBuild && !opening && !stunned) { cob->Call(COBFN_Activate); groundBlockingObjectMap->OpenBlockingYard(this, yardMap); opening = true; } if (quedBuild && inBuildStance && !stunned) { // start building a unit float3 buildPos = CalcBuildPos(); bool canBuild = true; std::vector<CUnit*> units = qf->GetUnitsExact(buildPos, 16); for (std::vector<CUnit*>::iterator ui = units.begin(); ui != units.end(); ++ui) { if ((*ui) != this) canBuild = false; } if (canBuild) { quedBuild = false; CUnit* b = unitLoader.LoadUnit(nextBuild, buildPos + float3(0.01f, 0.01f, 0.01f), team, true, buildFacing, this); b->lineage = this->lineage; if (!unitDef->canBeAssisted) { b->soloBuilder = this; b->AddDeathDependence(this); } AddDeathDependence(b); curBuild = b; cob->Call("StartBuilding"); int soundIdx = unitDef->sounds.build.getRandomIdx(); if (soundIdx >= 0) { sound->PlaySample( unitDef->sounds.build.getID(soundIdx), pos, unitDef->sounds.build.getVolume(0)); } } else { helper->BuggerOff(buildPos - float3(0.01f, 0, 0.02f), radius + 8); } } if (curBuild && !beingBuilt) { if (!stunned) { // factory not under construction and // nanolathing unit: continue building lastBuild = gs->frameNum; // buildPiece is the rotating platform const int buildPiece = GetBuildPiece(); CMatrix44f mat = localmodel->GetPieceMatrix(buildPiece); const int h = GetHeadingFromVector(mat[2], mat[10]); // rotate unit nanoframe with platform curBuild->heading = (h + GetHeadingFromFacing(buildFacing)) & 65535; const float3 buildPos = CalcBuildPos(buildPiece); curBuild->pos = buildPos; if (curBuild->floatOnWater) { curBuild->pos.y = ground->GetHeight(buildPos.x, buildPos.z); curBuild->pos.y -= curBuild->unitDef->waterline; } curBuild->midPos = curBuild->pos + (UpVector * curBuild->relMidPos.y); const CCommandQueue& queue = commandAI->commandQue; if(!queue.empty() && (queue.front().id == CMD_WAIT)) { curBuild->AddBuildPower(0, this); } else { if (curBuild->AddBuildPower(buildSpeed, this)) { CreateNanoParticle(); } } } if (!curBuild->beingBuilt && (!unitDef->fullHealthFactory || (curBuild->health >= curBuild->maxHealth))) { if (group && curBuild->group == 0) { curBuild->SetGroup(group); } bool userOrders = true; if (curBuild->commandAI->commandQue.empty() || (dynamic_cast<CMobileCAI*>(curBuild->commandAI) && ((CMobileCAI*)curBuild->commandAI)->unimportantMove)) { userOrders = false; const CFactoryCAI* facAI = (CFactoryCAI*) commandAI; const CCommandQueue& newUnitCmds = facAI->newUnitCommands; if (newUnitCmds.empty()) { SendToEmptySpot(curBuild); } else { // XXX the pathfinder sometimes... makes mistakes, try to hack around it // XXX note this qualifies as HACK HACK HACK float3 testpos = curBuild->pos + frontdir * (this->radius - 1.0f); Command c; c.id = CMD_MOVE; c.params.push_back(testpos.x); c.params.push_back(testpos.y); c.params.push_back(testpos.z); curBuild->commandAI->GiveCommand(c); for (CCommandQueue::const_iterator ci = newUnitCmds.begin(); ci != newUnitCmds.end(); ++ci) { c = *ci; c.options |= SHIFT_KEY; curBuild->commandAI->GiveCommand(c); } } waitCommandsAI.AddLocalUnit(curBuild, this); } eventHandler.UnitFromFactory(curBuild, this, userOrders); StopBuild(); } } if (((lastBuild + 200) < gs->frameNum) && !stunned && !quedBuild && opening && groundBlockingObjectMap->CanCloseYard(this)) { // close the factory after inactivity groundBlockingObjectMap->CloseBlockingYard(this, yardMap); opening = false; cob->Call(COBFN_Deactivate); } CBuilding::Update(); }
void CFactory::Update() { if(beingBuilt){ CUnit::Update(); return; } if(quedBuild && inBuildStance){ float3 buildPos = CalcBuildPos(); bool canBuild=true; std::vector<CUnit*> units=qf->GetUnitsExact(buildPos,16); for(std::vector<CUnit*>::iterator ui=units.begin();ui!=units.end();++ui){ if((*ui)!=this) canBuild=false; } if(canBuild){ quedBuild=false; CUnit* b=unitLoader.LoadUnit(nextBuild,buildPos+float3(0.01,0.01,0.01),team,true,buildFacing); AddDeathDependence(b); curBuild=b; animator->AnimAction("StartBuilding"); if(unitDef->sounds.build.id) sound->PlaySound(unitDef->sounds.build.id, pos, unitDef->sounds.build.volume); } else { helper->BuggerOff(buildPos-float3(0.01,0,0.02),radius+8); } } if(curBuild && !beingBuilt){ lastBuild=gs->frameNum; int buildPiece = GetBuildPiece(); CMatrix44f mat=localmodel->GetPieceMatrix(buildPiece); int h=GetHeadingFromVector(mat[2],mat[10]); curBuild->heading=h; float3 buildPos = curBuild->pos = CalcBuildPos(buildPiece); if(curBuild->floatOnWater) curBuild->pos.y=ground->GetHeight(buildPos.x,buildPos.z)-curBuild->unitDef->waterline; curBuild->midPos=curBuild->pos+UpVector*curBuild->relMidPos.y; if(curBuild->AddBuildPower(buildSpeed,this)){ std::vector<int> args; args.push_back(0); animator->AnimAction("QueryNanoPiece",args); if(unitDef->showNanoSpray){ float3 relWeaponFirePos=localmodel->GetPiecePos(args[0]); float3 weaponPos=pos + frontdir*relWeaponFirePos.z + updir*relWeaponFirePos.y + rightdir*relWeaponFirePos.x; float3 dif=curBuild->midPos-weaponPos; float l=dif.Length(); dif/=l; dif+=gs->randVector()*0.15f; float3 color= unitDef->nanoColor; if(gu->teamNanospray){ unsigned char* tcol=gs->Team(team)->color; color = float3(tcol[0]*(1./255.),tcol[1]*(1./255.),tcol[2]*(1./255.)); } new CGfxProjectile(weaponPos,dif,(int)l,color); } } else { if(!curBuild->beingBuilt){ if(group) curBuild->SetGroup(group); Command c; c.id=CMD_MOVE_STATE; c.options=0; c.params.push_back(moveState); curBuild->commandAI->GiveCommand(c); c.params.clear(); c.id=CMD_FIRE_STATE; c.params.push_back(fireState); curBuild->commandAI->GiveCommand(c); if(curBuild->commandAI->commandQue.empty() || (dynamic_cast<CMobileCAI*>(curBuild->commandAI) && ((CMobileCAI*)curBuild->commandAI)->unimportantMove)){ if(((CFactoryCAI*)commandAI)->newUnitCommands.empty()){ SendToEmptySpot(curBuild); } else { for(std::deque<Command>::iterator ci=((CFactoryCAI*)commandAI)->newUnitCommands.begin();ci!=((CFactoryCAI*)commandAI)->newUnitCommands.end();++ci) curBuild->commandAI->GiveCommand(*ci); } } StopBuild(); } } } if(lastBuild+200 < gs->frameNum && !quedBuild && opening && uh->CanCloseYard(this)){ readmap->CloseBlockingYard(this); opening=false; animator->AnimAction(ANIMFN_Deactivate); } CBuilding::Update(); }
void CFactory::AssignBuildeeOrders(CUnit* unit) { CCommandAI* unitCAI = unit->commandAI; CCommandQueue& unitCmdQue = unitCAI->commandQue; const CFactoryCAI* factoryCAI = static_cast<CFactoryCAI*>(commandAI); const CCommandQueue& factoryCmdQue = factoryCAI->newUnitCommands; if (factoryCmdQue.empty() && unitCmdQue.empty()) { SendToEmptySpot(unit); return; } Command c(CMD_MOVE); if (!unit->unitDef->canfly) { // HACK: when a factory has a rallypoint set far enough away // to trigger the non-admissable path estimators, we want to // avoid units getting stuck inside by issuing them an extra // move-order. However, this order can *itself* cause the PF // system to consider the path blocked if the extra waypoint // falls within the factory's confines, so use a wide berth. const float xs = unitDef->xsize * SQUARE_SIZE * 0.5f; const float zs = unitDef->zsize * SQUARE_SIZE * 0.5f; float tmpDst = 2.0f; float3 tmpPos = unit->pos + (frontdir * this->radius * tmpDst); if (buildFacing == FACING_NORTH || buildFacing == FACING_SOUTH) { while ((tmpPos.z >= unit->pos.z - zs && tmpPos.z <= unit->pos.z + zs)) { tmpDst += 0.5f; tmpPos = unit->pos + (frontdir * this->radius * tmpDst); } } else { while ((tmpPos.x >= unit->pos.x - xs && tmpPos.x <= unit->pos.x + xs)) { tmpDst += 0.5f; tmpPos = unit->pos + (frontdir * this->radius * tmpDst); } } c.PushPos(tmpPos.cClampInBounds()); } else { // dummy rallypoint for aircraft c.PushPos(unit->pos); } if (unitCmdQue.empty()) { unitCAI->GiveCommand(c); // copy factory orders for new unit for (CCommandQueue::const_iterator ci = factoryCmdQue.begin(); ci != factoryCmdQue.end(); ++ci) { Command c = *ci; c.options |= SHIFT_KEY; if (c.GetID() == CMD_MOVE) { const float3 p1 = c.GetPos(0); const float3 p2 = float3(p1.x + gs->randFloat() * TWOPI, p1.y, p1.z + gs->randFloat() * TWOPI); // apply a small amount of random jitter to move commands // such that new units do not all share the same goal-pos // and start forming a "trail" back to the factory exit c.SetPos(0, p2); } unitCAI->GiveCommand(c); } } else { unitCmdQue.push_front(c); } }