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

📄 builder.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:


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 + -