bool CFeature::AddBuildPower(float amount, CUnit* builder)
{
	float oldReclaimLeft = reclaimLeft;
	float fractionReclaimed;
	if(amount>0){
		
		// Check they are trying to repair a feature that can be resurrected
		if(createdFromUnit == "")
			return false;

		// 'Repairing' previously-sucked features prior to resurrection
		// This is reclaim-option independant - repairing features should always
		// be like other repairing - gradual and multi-unit
		// Lots of this code is stolen from unit->AddBuildPower
		
		isRepairingBeforeResurrect = true; // Stop them exploiting chunk reclaiming

		if (reclaimLeft >= 1)
			return false;		// cant repair a 'fresh' feature

		// Work out how much to try to put back, based on the speed this unit would reclaim at.
		float part=(100-amount)*0.02f/max(10.0f,(def->metal+def->energy));

		// Work out how much that will cost
		float metalUse=def->metal*part;
		float energyUse=def->energy*part;
		if (gs->Team(builder->team)->metal >= metalUse && gs->Team(builder->team)->energy >= energyUse)
		{
			builder->UseMetal(metalUse);
			builder->UseEnergy(energyUse);
			reclaimLeft+=part;
			if(reclaimLeft>=1)
			{
				isRepairingBeforeResurrect = false; // They can start reclaiming it again if they so wish
				reclaimLeft = 1;
			}
			return true;
		} else {
			// update the energy and metal required counts
			gs->Team(builder->team)->energyPull += energyUse;
			gs->Team(builder->team)->metalPull += metalUse;
		}
		return false;


	} else {
		// Reclaiming
		if(reclaimLeft <= 0)	// avoid multisuck when reclaim has already completed during this frame
			return false;
		
		if(isRepairingBeforeResurrect && modInfo->reclaimMethod > 1) // don't let them exploit chunk reclaim
			return false;
		
		if(modInfo->multiReclaim == 0 && lastReclaim == gs->frameNum) // make sure several units cant reclaim at once on a single feature
			return true;
		
		float part=(100-amount)*0.02f/max(10.0f,(def->metal+def->energy));
		reclaimLeft-=part;
		
		// Stop the last bit giving too much resource
		if(reclaimLeft < 0) reclaimLeft = 0;

		fractionReclaimed = oldReclaimLeft-reclaimLeft;

		if(modInfo->reclaimMethod == 1 && reclaimLeft == 0) // All-at-end method
		{
			builder->AddMetal(def->metal);
			builder->AddEnergy(def->energy);
		}
		else if(modInfo->reclaimMethod == 0) // Gradual reclaim
		{
			builder->AddMetal(def->metal * fractionReclaimed);
			builder->AddEnergy(def->energy * fractionReclaimed);
		}
		else  // Chunky reclaiming
		{
			// Work out how many chunk boundaries we crossed
			float chunkSize = 1.0f / modInfo->reclaimMethod;
			int oldChunk = ChunkNumber(oldReclaimLeft);
			int newChunk = ChunkNumber(reclaimLeft);
			if (oldChunk != newChunk)
			{
				float noChunks = (float)oldChunk - (float)newChunk;
				builder->AddMetal(noChunks * def->metal * chunkSize);
				builder->AddEnergy(noChunks * def->energy * chunkSize);
			}
		}

		// Has the reclaim finished?
		if(reclaimLeft<=0)
		{
			featureHandler->DeleteFeature(this);
			return false;
		}

		lastReclaim=gs->frameNum;
		return true;
	}
	// Should never get here
	assert(false);
	return false;
}
Exemple #2
0
bool CFeature::AddBuildPower(float amount, CUnit* builder)
{
	const float oldReclaimLeft = reclaimLeft;

	if (amount > 0.0f) {
		// Check they are trying to repair a feature that can be resurrected
		if (udef == NULL) {
			return false;
		}

		// 'Repairing' previously-sucked features prior to resurrection
		// This is reclaim-option independant - repairing features should always
		// be like other repairing - gradual and multi-unit
		// Lots of this code is stolen from unit->AddBuildPower

		isRepairingBeforeResurrect = true; // Stop them exploiting chunk reclaiming

		if (reclaimLeft >= 1) {
			return false; // cant repair a 'fresh' feature
		}

		if (reclaimLeft <= 0) {
			return false; // feature most likely has been deleted
		}

		// Work out how much to try to put back, based on the speed this unit would reclaim at.
		const float part = amount / def->reclaimTime;

		// Work out how much that will cost
		const float metalUse  = part * def->metal;
		const float energyUse = part * def->energy;
		if ((teamHandler->Team(builder->team)->metal  >= metalUse)  &&
		    (teamHandler->Team(builder->team)->energy >= energyUse) &&
				(!luaRules || luaRules->AllowFeatureBuildStep(builder, this, part))) {
			builder->UseMetal(metalUse);
			builder->UseEnergy(energyUse);
			reclaimLeft+=part;
			if (reclaimLeft >= 1) {
				isRepairingBeforeResurrect = false; // They can start reclaiming it again if they so wish
				reclaimLeft = 1;
			} else if (reclaimLeft <= 0) {
				// this can happen when a mod tampers the feature in AllowFeatureBuildStep
				featureHandler->DeleteFeature(this);
				return false;
			}
			return true;
		}
		else {
			// update the energy and metal required counts
			teamHandler->Team(builder->team)->energyPull += energyUse;
			teamHandler->Team(builder->team)->metalPull  += metalUse;
		}
		return false;
	}
	else { // Reclaiming
		// avoid multisuck when reclaim has already completed during this frame
		if (reclaimLeft <= 0) {
			return false;
		}

		// don't let them exploit chunk reclaim
		if (isRepairingBeforeResurrect && (modInfo.reclaimMethod > 1)) {
			return false;
		}

		// make sure several units cant reclaim at once on a single feature
		if ((modInfo.multiReclaim == 0) && (lastReclaim == gs->frameNum)) {
			return true;
		}

		const float part = (-amount) / def->reclaimTime;

		if (luaRules && !luaRules->AllowFeatureBuildStep(builder, this, -part)) {
			return false;
		}

		float reclaimLeftTemp = reclaimLeft - part;
		// stop the last bit giving too much resource
		if (reclaimLeftTemp < 0) {
			reclaimLeftTemp = 0;
		}

		const float fractionReclaimed = oldReclaimLeft - reclaimLeftTemp;
		const float metalFraction = def->metal * fractionReclaimed;
		const float energyFraction = def->energy * fractionReclaimed;
		const float energyUseScaled = metalFraction * modInfo.reclaimFeatureEnergyCostFactor;

		if (!builder->UseEnergy(energyUseScaled)) {
			teamHandler->Team(builder->team)->energyPull += energyUseScaled;
			return false;
		}

		reclaimLeft = reclaimLeftTemp;

		if ((modInfo.reclaimMethod == 1) && (reclaimLeft == 0)) {
			// All-at-end method
			builder->AddMetal(def->metal, false);
			builder->AddEnergy(def->energy, false);
		}
		else if (modInfo.reclaimMethod == 0) {
			// Gradual reclaim
			builder->AddMetal(metalFraction, false);
			builder->AddEnergy(energyFraction, false);
		}
		else {
			// Chunky reclaiming, work out how many chunk boundaries we crossed
			const float chunkSize = 1.0f / modInfo.reclaimMethod;
			const int oldChunk = ChunkNumber(oldReclaimLeft);
			const int newChunk = ChunkNumber(reclaimLeft);
			if (oldChunk != newChunk) {
				const float noChunks = (float)oldChunk - (float)newChunk;
				builder->AddMetal(noChunks * def->metal * chunkSize, false);
				builder->AddEnergy(noChunks * def->energy * chunkSize, false);
			}
		}

		// Has the reclaim finished?
		if (reclaimLeft <= 0) {
			featureHandler->DeleteFeature(this);
			return false;
		}

		lastReclaim = gs->frameNum;
		return true;
	}

	// Should never get here
	assert(false);
	return false;
}
Exemple #3
0
bool CFeature::AddBuildPower(CUnit* builder, float amount)
{
	const float oldReclaimLeft = reclaimLeft;

	if (amount > 0.0f) {
		// 'Repairing' previously-sucked features prior to resurrection
		// This is reclaim-option independant - repairing features should always
		// be like other repairing - gradual and multi-unit
		// Lots of this code is stolen from unit->AddBuildPower
		//
		// Check they are trying to repair a feature that can be resurrected
		if (udef == nullptr)
			return false;

		isRepairingBeforeResurrect = true; // Stop them exploiting chunk reclaiming

		// cannot repair a 'fresh' feature
		if (reclaimLeft >= 1.0f)
			return false;
		// feature most likely has been deleted
		if (reclaimLeft <= 0.0f)
			return false;

		const CTeam* builderTeam = teamHandler->Team(builder->team);

		// Work out how much to try to put back, based on the speed this unit would reclaim at.
		const float step = amount / def->reclaimTime;

		// Work out how much that will cost
		const float metalUse  = step * def->metal;
		const float energyUse = step * def->energy;
		const bool canExecRepair = (builderTeam->res.metal >= metalUse && builderTeam->res.energy >= energyUse);
		const bool repairAllowed = !canExecRepair ? false : eventHandler.AllowFeatureBuildStep(builder, this, step);

		if (repairAllowed) {
			builder->UseMetal(metalUse);
			builder->UseEnergy(energyUse);

			reclaimLeft += step;
			resources.metal  += metalUse;
			resources.energy += energyUse;
			resources.metal  = std::min(resources.metal, def->metal);
			resources.energy = std::min(resources.energy, def->energy);

			if (reclaimLeft >= 1.0f) {
				isRepairingBeforeResurrect = false; // They can start reclaiming it again if they so wish
				reclaimLeft = 1;
			} else if (reclaimLeft <= 0.0f) {
				// this can happen when a mod tampers the feature in AllowFeatureBuildStep
				featureHandler->DeleteFeature(this);
				return false;
			}

			return true;
		}

		// update the energy and metal required counts
		teamHandler->Team(builder->team)->resPull.energy += energyUse;
		teamHandler->Team(builder->team)->resPull.metal  += metalUse;
		return false;
	}

	// Reclaiming
	// avoid multisuck when reclaim has already completed during this frame
	if (reclaimLeft <= 0.0f)
		return false;

	// don't let them exploit chunk reclaim
	if (isRepairingBeforeResurrect && (modInfo.reclaimMethod > 1))
		return false;

	// make sure several units cant reclaim at once on a single feature
	if ((modInfo.multiReclaim == 0) && (lastReclaim == gs->frameNum))
		return true;

	const float step = (-amount) / def->reclaimTime;

	if (!eventHandler.AllowFeatureBuildStep(builder, this, -step))
		return false;

	// stop the last bit giving too much resource
	const float reclaimLeftTemp = std::max(0.0f, reclaimLeft - step);
	const float fractionReclaimed = oldReclaimLeft - reclaimLeftTemp;
	const float metalFraction  = std::min(def->metal  * fractionReclaimed, resources.metal);
	const float energyFraction = std::min(def->energy * fractionReclaimed, resources.energy);
	const float energyUseScaled = metalFraction * modInfo.reclaimFeatureEnergyCostFactor;

	SResourceOrder order;
	order.quantum    = false;
	order.overflow   = builder->harvestStorage.empty();
	order.separate   = true;
	order.use.energy = energyUseScaled;

	if (reclaimLeftTemp == 0.0f) {
		// always give remaining resources at the end
		order.add.metal  = resources.metal;
		order.add.energy = resources.energy;
	}
	else if (modInfo.reclaimMethod == 0) {
		// Gradual reclaim
		order.add.metal  = metalFraction;
		order.add.energy = energyFraction;
	}
	else if (modInfo.reclaimMethod == 1) {
		// All-at-end method
		// see `reclaimLeftTemp == 0.0f` case
	}
	else {
		// Chunky reclaiming, work out how many chunk boundaries we crossed
		const float chunkSize = 1.0f / modInfo.reclaimMethod;
		const int oldChunk = ChunkNumber(oldReclaimLeft);
		const int newChunk = ChunkNumber(reclaimLeft);

		if (oldChunk != newChunk) {
			const float numChunks = oldChunk - newChunk;
			order.add.metal  = std::min(numChunks * def->metal * chunkSize,  resources.metal);
			order.add.energy = std::min(numChunks * def->energy * chunkSize, resources.energy);
		}
	}

	if (!builder->IssueResourceOrder(&order))
		return false;

	resources  -= order.add;
	reclaimLeft = reclaimLeftTemp;
	lastReclaim = gs->frameNum;

	// Has the reclaim finished?
	if (reclaimLeft <= 0) {
		featureHandler->DeleteFeature(this);
		return false;
	}

	return true;
}