void CFactory::StartBuild(const UnitDef* buildeeDef) { const float3& buildPos = CalcBuildPos(); const bool blocked = groundBlockingObjectMap->GroundBlocked(buildPos, this); // wait until buildPos is no longer blocked (eg. by a previous buildee) // // it might rarely be the case that a unit got stuck inside the factory // or died right after completion and left some wreckage, but that is up // to players to fix (we no longer broadcast BuggerOff directives, since // those are indiscriminate and ineffective) if (blocked) return; CUnit* b = unitLoader->LoadUnit(buildeeDef, buildPos, team, true, buildFacing, this); if (!unitDef->canBeAssisted) { b->soloBuilder = this; b->AddDeathDependence(this, DEPENDENCE_BUILDER); } AddDeathDependence(b, DEPENDENCE_BUILD); script->StartBuilding(); // set curBuildDef to NULL to indicate construction // has started, otherwise we would keep being called curBuild = b; curBuildDef = NULL; #if (PLAY_SOUNDS == 1) if (losStatus[gu->myAllyTeam] & LOS_INLOS) { Channels::General.PlayRandomSample(unitDef->sounds.build, buildPos); } #endif }
void CFactory::UpdateBuild(CUnit* buildee) { if (stunned) return; // factory not under construction and // nanolathing unit: continue building lastBuildUpdateFrame = gs->frameNum; // buildPiece is the rotating platform const int buildPiece = GetBuildPiece(); const float3& buildPos = CalcBuildPos(buildPiece); const CMatrix44f& mat = script->GetPieceMatrix(buildPiece); const int h = GetHeadingFromVector(mat[2], mat[10]); //! x.z, z.z float3 buildeePos = buildPos; // rotate unit nanoframe with platform buildee->heading = (-h + GetHeadingFromFacing(buildFacing)) & (SPRING_CIRCLE_DIVS - 1); if (buildee->unitDef->floatOnWater && (buildeePos.y <= 0.0f)) buildeePos.y = -buildee->unitDef->waterline; buildee->Move3D(buildeePos, false); buildee->UpdateDirVectors(false); buildee->UpdateMidAndAimPos(); const CCommandQueue& queue = commandAI->commandQue; if (!queue.empty() && (queue.front().GetID() == CMD_WAIT)) { buildee->AddBuildPower(0, this); } else { if (buildee->AddBuildPower(buildSpeed, this)) { CreateNanoParticle(); } } }
void CFactory::Update() { if (beingBuilt) { // factory under construction CUnit::Update(); return; } if (quedBuild && !opening && !stunned) { script->Activate(); groundBlockingObjectMap->OpenBlockingYard(this, curYardMap); opening = true; } if (quedBuild && inBuildStance && !stunned) { // start building a unit const float3 buildPos = CalcBuildPos(); const CSolidObject* solidObj = groundBlockingObjectMap->GroundBlocked(buildPos); if (solidObj == NULL || (dynamic_cast<const CUnit*>(solidObj) == this)) { quedBuild = false; CUnit* b = unitLoader.LoadUnit(nextBuild, buildPos + float3(0.01f, 0.01f, 0.01f), team, true, buildFacing, this); if (!unitDef->canBeAssisted) { b->soloBuilder = this; b->AddDeathDependence(this); } AddDeathDependence(b); curBuild = b; script->StartBuilding(); int soundIdx = unitDef->sounds.build.getRandomIdx(); if (soundIdx >= 0) { Channels::UnitReply.PlaySample( unitDef->sounds.build.getID(soundIdx), pos, unitDef->sounds.build.getVolume(0)); } } else { helper->BuggerOff(buildPos - float3(0.01f, 0, 0.02f), radius + 8, true, true, NULL); } } 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(); const CMatrix44f& mat = script->GetPieceMatrix(buildPiece); const int h = GetHeadingFromVector(mat[2], mat[10]); //! x.z, z.z // rotate unit nanoframe with platform curBuild->heading = (h + GetHeadingFromFacing(buildFacing)) & 65535; const float3 buildPos = CalcBuildPos(buildPiece); curBuild->pos = buildPos; if (curBuild->floatOnWater) { float waterline = ground->GetHeight(buildPos.x, buildPos.z) - curBuild->unitDef->waterline; if (waterline > curBuild->pos.y) curBuild->pos.y = 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; AssignBuildeeOrders(curBuild); 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, curYardMap); opening = false; script->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::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(); }