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; }
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; }
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; }