📄 builder.cpp
字号:
void CBuilder::SetRepairTarget(CUnit* target)
{
if(target==curBuild)
return;
StopBuild(false);
TempHoldFire();
curBuild=target;
AddDeathDependence(curBuild);
if(!target->groundLevelled) {
//resume levelling the ground
tx1 = (int)max((float)0,(target->pos.x - (target->unitDef->xsize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
tx2 = min(gs->mapx,tx1+target->unitDef->xsize);
tz1 = (int)max((float)0,(target->pos.z - (target->unitDef->ysize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
tz2 = min(gs->mapy,tz1+target->unitDef->ysize);
terraformCenter = target->pos;
terraformRadius = (tx1 - tx2) * SQUARE_SIZE;
terraformType=Terraform_Building;
terraforming = true;
}
SetBuildStanceToward(target->pos);
}
void CBuilder::SetReclaimTarget(CSolidObject* target)
{
if(dynamic_cast<CFeature*>(target) && !((CFeature*) target)->def->reclaimable){
return;
}
if(dynamic_cast<CUnit*>(target) && !((CUnit*) target)->unitDef->reclaimable){
return;
}
if(curReclaim==target || this == target){
return;
}
StopBuild(false);
TempHoldFire();
curReclaim=target;
AddDeathDependence(curReclaim);
SetBuildStanceToward(target->pos);
}
void CBuilder::SetResurrectTarget(CFeature* target)
{
if(curResurrect==target || target->createdFromUnit=="")
return;
StopBuild(false);
TempHoldFire();
curResurrect=target;
AddDeathDependence(curResurrect);
SetBuildStanceToward(target->pos);
}
void CBuilder::SetCaptureTarget(CUnit* target)
{
if(target==curCapture)
return;
StopBuild(false);
TempHoldFire();
curCapture=target;
AddDeathDependence(curCapture);
SetBuildStanceToward(target->pos);
}
void CBuilder::StartRestore(float3 centerPos, float radius)
{
StopBuild(false);
TempHoldFire();
terraforming=true;
terraformType=Terraform_Restore;
terraformCenter=centerPos;
terraformRadius=radius;
tx1 = (int)max((float)0,(centerPos.x-radius)/SQUARE_SIZE);
tx2 = (int)min((float)gs->mapx,(centerPos.x+radius)/SQUARE_SIZE);
tz1 = (int)max((float)0,(centerPos.z-radius)/SQUARE_SIZE);
tz2 = (int)min((float)gs->mapy,(centerPos.z+radius)/SQUARE_SIZE);
float tcost=0;
float* heightmap = readmap->GetHeightmap();
for(int z=tz1; z<=tz2; z++){
for(int x=tx1; x<=tx2; x++){
float delta=readmap->orgheightmap[z*(gs->mapx+1)+x]-heightmap[z*(gs->mapx+1)+x];
tcost+=fabs(delta);
}
}
myTerraformLeft=tcost;
SetBuildStanceToward(centerPos);
}
void CBuilder::StopBuild(bool callScript)
{
if(curBuild)
DeleteDeathDependence(curBuild);
if(curReclaim)
DeleteDeathDependence(curReclaim);
if(helpTerraform)
DeleteDeathDependence(helpTerraform);
if(curResurrect)
DeleteDeathDependence(curResurrect);
if(curCapture)
DeleteDeathDependence(curCapture);
curBuild=0;
curReclaim=0;
helpTerraform=0;
curResurrect=0;
curCapture=0;
terraforming=false;
if(callScript)
cob->Call("StopBuilding");
ReleaseTempHoldFire();
// logOutput.Print("stop build");
}
bool CBuilder::StartBuild(BuildInfo& buildInfo)
{
StopBuild(false);
// logOutput.Print("start build");
buildInfo.pos=helper->Pos2BuildPos(buildInfo);
CFeature* feature;
// Pass -1 as allyteam to behave like we have maphack.
// This is needed to prevent building on top of cloaked stuff.
int canBuild=uh->TestUnitBuildSquare(buildInfo, feature, -1);
if(canBuild<2){
CUnit* u=helper->GetClosestFriendlyUnit(buildInfo.pos,5,allyteam);
if(u && u->unitDef==buildInfo.def && unitDef->canAssist){
curBuild=u;
AddDeathDependence(u);
SetBuildStanceToward(buildInfo.pos);
return true;
}
return false;
}
if(feature)
return false;
const UnitDef* unitDef = buildInfo.def;
SetBuildStanceToward(buildInfo.pos);
nextBuildType=buildInfo.def->name;
nextBuildPos=buildInfo.pos;
CUnit* b = unitLoader.LoadUnit(nextBuildType, nextBuildPos, team,
true, buildInfo.buildFacing, this);
if (mapDamage->disabled || !unitDef->levelGround || unitDef->floater ||
(unitDef->canmove && (unitDef->speed > 0.0f))) {
// skip the terraforming job.
b->terraformLeft = 0;
b->groundLevelled=true;
}
else {
tx1 = (int)max((float)0,(b->pos.x - (b->unitDef->xsize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
tx2 = min(gs->mapx,tx1+b->unitDef->xsize);
tz1 = (int)max((float)0,(b->pos.z - (b->unitDef->ysize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
tz2 = min(gs->mapy,tz1+b->unitDef->ysize);
b->terraformLeft = CalculateBuildTerraformCost(buildInfo);
b->groundLevelled=false;
terraforming=true;
terraformType=Terraform_Building;
terraformRadius=(tx2-tx1)*SQUARE_SIZE;
terraformCenter = b->pos;
}
if (!this->unitDef->canBeAssisted) {
b->soloBuilder = this;
b->AddDeathDependence(this);
}
b->lineage = this->lineage;
AddDeathDependence(b);
curBuild=b;
if (mapDamage->disabled && !(curBuild->floatOnWater)) {
/* The ground isn't going to be terraformed.
* When the building is completed, it'll 'pop'
* into the correct height for the (un-flattened)
* terrain it's on.
*
* To prevent this visual artifact, put the building
* at the 'right' height to begin with.
*
* Duplicated from CMoveType::SlowUpdate(), which
* is why we use the regular code for floating things.
*/
curBuild->pos.y=ground->GetHeight2(curBuild->pos.x,curBuild->pos.z);
curBuild->midPos.y=curBuild->pos.y+curBuild->relMidPos.y;
}
else {
float d=nextBuildPos.y-curBuild->pos.y;
curBuild->pos.y+=d;
curBuild->midPos.y+=d;
}
return true;
}
float CBuilder::CalculateBuildTerraformCost(BuildInfo& buildInfo)
{
float3& buildPos=buildInfo.pos;
float tcost=0;
float* heightmap = readmap->GetHeightmap();
for(int z=tz1; z<=tz2; z++){
for(int x=tx1; x<=tx2; x++){
float delta=buildPos.y-heightmap[z*(gs->mapx+1)+x];
float cost;
if(delta>0){
cost=max(3.f,heightmap[z*(gs->mapx+1)+x]-readmap->orgheightmap[z*(gs->mapx+1)+x]+delta*0.5f);
} else {
cost=max(3.f,readmap->orgheightmap[z*(gs->mapx+1)+x]-heightmap[z*(gs->mapx+1)+x]-delta*0.5f);
}
tcost+=fabs(delta)*cost;
}
}
return tcost;
}
void CBuilder::DependentDied(CObject *o)
{
if(o==curBuild){
curBuild=0;
StopBuild();
}
if(o==curReclaim){
curReclaim=0;
StopBuild();
}
if(o==helpTerraform){
helpTerraform=0;
StopBuild();
}
if(o==curResurrect){
curResurrect=0;
StopBuild();
}
if(o==curCapture){
curCapture=0;
StopBuild();
}
CUnit::DependentDied(o);
}
void CBuilder::SetBuildStanceToward(float3 pos)
{
float3 wantedDir=(pos-this->midPos).Normalize();
short int h=GetHeadingFromVector(wantedDir.x,wantedDir.z);
short int p=(short int) (asin(wantedDir.dot(updir))*(32768/PI));
short int pitch=(short int) (asin(frontdir.dot(updir))*(32768/PI));
std::vector<int> args;
args.push_back(short(h-heading));
args.push_back(short(p-pitch));
cob->Call("StartBuilding", args);
int soundIdx = unitDef->sounds.build.getRandomIdx();
if (soundIdx >= 0) {
sound->PlaySample(
unitDef->sounds.build.getID(soundIdx), pos,
unitDef->sounds.build.getVolume(soundIdx));
}
}
void CBuilder::HelpTerraform(CBuilder* unit)
{
if(helpTerraform==unit)
return;
StopBuild(false);
helpTerraform=unit;
AddDeathDependence(helpTerraform);
SetBuildStanceToward(unit->terraformCenter);
}
void CBuilder::CreateNanoParticle(float3 goal, float radius, bool inverse)
{
std::vector<int> args;
args.push_back(0);
cob->Call("QueryNanoPiece", args);
ENTER_UNSYNCED;
if (ph->currentParticles < ph->maxParticles) {
if (!unitDef->showNanoSpray)
return;
float3 relWeaponFirePos = localmodel->GetPiecePos(args[0]);
float3 weaponPos = pos + frontdir * relWeaponFirePos.z + updir * relWeaponFirePos.y + rightdir * relWeaponFirePos.x;
float3 dif = goal - weaponPos;
float l = dif.Length();
dif /= l;
float3 error = gu->usRandVector() * (radius / l);
float3 color = unitDef->nanoColor;
if (gu->teamNanospray) {
unsigned char* tcol = gs->Team(team)->color;
color = float3(tcol[0] * (1.f / 255.f), tcol[1] * (1.f / 255.f), tcol[2] * (1.f / 255.f));
}
if (inverse) {
SAFE_NEW CGfxProjectile(weaponPos + (dif + error) * l, -(dif + error) * 3, int(l / 3), color);
} else {
SAFE_NEW CGfxProjectile(weaponPos, (dif + error) * 3, int(l / 3), color);
}
}
ENTER_SYNCED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -